Skip to content

Commit 6782a9d

Browse files
committed
fix: install system service as root in cloudformation
1 parent 65c2b26 commit 6782a9d

4 files changed

Lines changed: 61 additions & 2 deletions

File tree

docs/deploy/aws.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,13 @@ You can check the installed version on the instance:
118118
opencode-cloud --version
119119
```
120120

121+
CloudFormation installs a **system-level** systemd unit that runs as `ubuntu`.
122+
Check service status with:
123+
124+
```bash
125+
sudo systemctl status opencode-cloud
126+
```
127+
121128
## Provisioning Script Architecture
122129

123130
The CloudFormation and cloud-init templates now bootstrap provisioning from

packages/core/src/platform/systemd.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,17 @@ impl SystemdManager {
6868
// This gives enough window for the allowed burst of restarts
6969
let start_limit_interval = config.restart_delay * config.restart_retries * 2;
7070

71+
let service_user_line = if !self.user_mode {
72+
std::env::var("OPENCODE_SERVICE_USER")
73+
.ok()
74+
.map(|value| value.trim().to_string())
75+
.filter(|value| !value.is_empty())
76+
.map(|value| format!("User={value}\n"))
77+
.unwrap_or_default()
78+
} else {
79+
String::new()
80+
};
81+
7182
format!(
7283
r#"[Unit]
7384
Description=opencode-cloud container service
@@ -77,7 +88,7 @@ Requires=docker.service
7788
7889
[Service]
7990
Type=simple
80-
ExecStart={exec_start}
91+
{service_user_line}ExecStart={exec_start}
8192
ExecStop={exec_stop}
8293
Restart=on-failure
8394
RestartSec={restart_delay}s
@@ -92,6 +103,7 @@ WantedBy=default.target
92103
restart_delay = config.restart_delay,
93104
restart_retries = config.restart_retries,
94105
start_limit_interval = start_limit_interval,
106+
service_user_line = service_user_line,
95107
)
96108
}
97109

@@ -361,6 +373,25 @@ mod tests {
361373
assert!(unit.contains("StartLimitIntervalSec=100")); // 10 * 5 * 2
362374
}
363375

376+
#[test]
377+
fn test_generate_unit_file_system_user() {
378+
std::env::set_var("OPENCODE_SERVICE_USER", "ubuntu");
379+
380+
let manager = SystemdManager::new("system");
381+
let config = ServiceConfig {
382+
executable_path: PathBuf::from("/usr/bin/occ"),
383+
restart_retries: 3,
384+
restart_delay: 5,
385+
boot_mode: "system".to_string(),
386+
};
387+
388+
let unit = manager.generate_unit_file(&config);
389+
390+
assert!(unit.contains("User=ubuntu"));
391+
392+
std::env::remove_var("OPENCODE_SERVICE_USER");
393+
}
394+
364395
#[test]
365396
fn test_is_installed_returns_false_for_nonexistent() {
366397
let manager = SystemdManager::new("user");

scripts/provisioning/opencode-cloud-setup-cloudformation.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ opencode_setup_log "opencode-cloud setup: set boot_mode=system for cloudformatio
144144
opencode_setup_run_as_user "opencode-cloud config set boot_mode system"
145145

146146
opencode_setup_log "opencode-cloud setup: install service (system-level)"
147-
opencode_setup_run_as_user "opencode-cloud install --force"
147+
opencode_setup_run_as_root_with_user_env "opencode-cloud install --force"
148148
opencode_setup_log "opencode-cloud setup: service install complete (system-level)"
149149

150150
opencode_setup_log "opencode-cloud setup: restart container after service install"

scripts/provisioning/opencode-cloud-setup.sh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,27 @@ opencode_setup_run_as_user() {
141141
fi
142142
}
143143

144+
opencode_setup_run_as_root_with_user_env() {
145+
local cmd="$*"
146+
local target_home="${OPENCODE_SETUP_HOME:-/root}"
147+
local service_user="${OPENCODE_SETUP_USER:-}"
148+
local target_path="$target_home/.cargo/bin:$PATH"
149+
local -a env_args=(
150+
"HOME=$target_home"
151+
"XDG_CONFIG_HOME=$target_home/.config"
152+
"XDG_DATA_HOME=$target_home/.local/share"
153+
"XDG_STATE_HOME=$target_home/.local/state"
154+
"XDG_CACHE_HOME=$target_home/.cache"
155+
"PATH=$target_path"
156+
)
157+
158+
if [ -n "$service_user" ]; then
159+
env_args=("OPENCODE_SERVICE_USER=$service_user" "${env_args[@]}")
160+
fi
161+
162+
env "${env_args[@]}" bash -lc "$cmd"
163+
}
164+
144165
opencode_setup_ensure_rust_toolchain() {
145166
if ! opencode_setup_run_as_user "command -v cargo >/dev/null 2>&1"; then
146167
opencode_setup_log "opencode-cloud setup: install rust toolchain"

0 commit comments

Comments
 (0)