Program Files 配下への書き込み、1024 未満のポートの bind、サービスの登録は、Windows なら管理者(UAC で昇格したプロセス)、macOS / Linux なら root でないと失敗します。操作の直前に権限を確認し、無ければ「管理者として起動し直してください」と案内するだけで問い合わせがかなり減ります。判定はフロントからはできないので Rust 側で行います。Windows は is_elevated クレート、Unix 系は nix の geteuid() を使い、cfg で分岐させます。
前提条件
クレートは OS ごとに分けて依存に入れます。is_elevated は Windows 専用で、通常の [dependencies] に書くと macOS / Linux のビルドが通りません。プラグインと権限設定は不要です。
src-tauri/Cargo.toml:
[target.'cfg(windows)'.dependencies]
is_elevated = "0.1"
[target.'cfg(unix)'.dependencies]
nix = { version = "0.31", features = ["user"] }
1. フロントエンドから実装する (TypeScript)
import { invoke } from '@tauri-apps/api/core';
async function ensureAdmin(): Promise<boolean> {
const elevated = await invoke<boolean>('is_admin');
if (!elevated) {
document.getElementById('warn')!.textContent =
'この操作には管理者権限が必要です。アプリを管理者として起動し直してください。';
}
return elevated;
}
document.getElementById('install-service')!.addEventListener('click', async () => {
if (await ensureAdmin()) await invoke('install_service');
});
2. バックエンドから実装する (Rust)
src-tauri/src/lib.rs:
#[cfg(windows)]
fn elevated() -> bool {
is_elevated::is_elevated() // TokenElevation を見る。UAC で昇格していれば true
}
#[cfg(unix)]
fn elevated() -> bool {
nix::unistd::geteuid().is_root() // 実効ユーザー ID が 0 なら root。sudo 経由でも true
}
#[tauri::command]
fn is_admin() -> bool {
elevated()
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![is_admin])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
クレートを増やしたくない場合、Unix は libc::geteuid() == 0(unsafe が必要)、Windows は windows クレートで OpenProcessToken → GetTokenInformation(TokenElevation) を呼べば同じことができます。
管理者権限で再起動する
昇格は「起動時」にしか決められません。実行中のプロセスを後から昇格させる API は無いので、自分自身を昇格付きで起動し直してから終了します。
- Windows:
ShellExecuteWの動詞runasで自分の exe を起動すると UAC ダイアログが出ます。手軽にはStart-Process -FilePath <exe> -Verb RunAsを PowerShell 経由で実行し、その後app.exit(0)します。常に管理者で起動させたいアプリは、tauri_build::WindowsAttributes::app_manifest()でrequestedExecutionLevel="requireAdministrator"を含むマニフェストを埋め込みます。 - macOS: GUI アプリ全体を root で動かす仕組みはありません。特権が必要な処理だけを
osascript -e 'do shell script "..." with administrator privileges'に切り出すか、ヘルパーツールを別途インストールします。 - Linux:
pkexec <exe>で Polkit の認証ダイアログが出ますが、root で起動した WebKitGTK アプリは環境によって警告が出ます。macOS 同様「特権が必要な処理だけを外に出す」設計が無難です。
動作確認
通常のターミナルから npm run tauri dev を実行すると is_admin は false、管理者として開いた PowerShell(Windows)や sudo npm run tauri dev(macOS / Linux)から実行すると true になります。ビルド後の exe を右クリックして「管理者として実行」でも確認できます。
よくあるエラーと対処法
- macOS / Linux で
is_elevatedに関するビルドエラー:is_elevatedを[dependencies]に直接書いています。[target.'cfg(windows)'.dependencies]へ移します。 nix::unistd::geteuidが見つからない:nixのuserフィーチャーが無効です。features = ["user"]を付けます。- 管理者アカウントなのに
false: Windows の管理者アカウントでも、UAC を通らずに起動したプロセスは制限付きトークンで動きます。判定しているのはアカウント種別ではなくプロセスの昇格状態なので、正しい挙動です。 - NSIS で
installMode: "perMachine"にしたのにfalse:installModeは「インストーラーが管理者権限を要求するか」の設定で、インストール後のアプリ実行には影響しません。アプリ自体を昇格させるには前述のマニフェストが必要です。
OS ごとの違いと注意点
- Windows: UAC を無効にした環境では、管理者アカウントのプロセスは常に昇格状態になります。
runasでの再起動は毎回 UAC ダイアログが出るので、必要な操作の直前だけにします。 - macOS:
geteuid()が 0 になるのはsudoでターミナルから起動した場合だけです。App Store 配布アプリはサンドボックスの制約で root 実行自体が想定されていません。 - NSIS の
installMode:currentUser(既定。管理者不要でユーザーフォルダに入る)、perMachine(Program Filesに入るためインストール時のみ管理者が必要)、both(インストール時に選択)の 3 択です。perMachineにすると、アプリ実行時に自分のインストール先へ書き込めなくなる点に注意してください。
