-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathorbstack-cloud-init.yaml
More file actions
185 lines (174 loc) · 9.12 KB
/
Copy pathorbstack-cloud-init.yaml
File metadata and controls
185 lines (174 loc) · 9.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#cloud-config
#
# OrbStack VM prepared for `remo add` + `remo configure` (remo >= 4.3.0).
#
# orb create ubuntu remo-mbp -u orbadmin -c docs/examples/orbstack-cloud-init.yaml
#
# Deliberately minimal: this installs ONLY what Ansible needs in order to
# connect and take over. Docker, Node.js, zellij, fzf, the GitHub CLI, the
# devcontainers CLI and remo-host are all installed by `remo configure`, which
# is idempotent — duplicating any of that here would only drift.
#
# ---------------------------------------------------------------------------
# `-u orbadmin` IS NOT OPTIONAL. Leave it off and this file does not work.
# ---------------------------------------------------------------------------
# OrbStack creates a Linux account named after your macOS user and pins it to
# your **macOS UID** — 501 on a normal Mac, not 1000 — and it does so AFTER
# cloud-init has finished. Two consequences, both verified on OrbStack 2.2.1 +
# Ubuntu 26.04 (2026-08-06):
#
# * Anything cloud-init does to "whichever account holds UID 1000" runs before
# that account exists. During runcmd the only UID-1000 account is the image's
# transient default user, so an SSH key installed there lands in a home
# directory OrbStack later deletes. cloud-init still reports `status: done`
# with `errors: []` — the only symptom is `remo add --verify` failing to
# authenticate afterwards.
# * OrbStack renumbers its own default user even if cloud-init already created
# it at UID 1000. A `remo` account made here was moved 1000 -> 501 when
# `remo` was also OrbStack's default user name.
#
# Naming OrbStack's default user something else (`orbadmin`) leaves UID 1000
# free for the account this file creates. `orbadmin` is vestigial — it exists so
# `orb` has its integration account, and you never log into it.
#
# WHY UID 1000 MATTERS TO REMO
#
# remo's user_setup role pins remo_user to UID 1000 (it matches the devcontainer
# `vscode` user). Register an account at any other UID and `remo configure`
# reaches "Create remo user with UID 1000" and runs `usermod -u 1000` against
# the very account Ansible is logged in as — which shadow-utils refuses to do
# for a user with running processes. Creating `remo` at 1000 up front makes that
# task a no-op and means the UID-displacement branch (which rewrites /etc/passwd
# and drops the live SSH session) never fires at all.
#
# OPTIONAL: add `--isolated` to the `orb create` line to turn off OrbStack's Mac
# file sharing and integration — no /mnt/mac, no ~/.ssh symlinked back to macOS.
# It is independent of the UID fix above (both were verified with and without
# it); use it if you want the VM to be a plain Linux box.
#
# ---------------------------------------------------------------------------
# WHICH NAME TO REGISTER
# ---------------------------------------------------------------------------
# Do NOT register the VM's own IP. An OrbStack VM is not on your LAN: it gets a
# static address on OrbStack's internal bridge, and OrbStack has no bridged /
# DHCP-from-your-router mode, so that address means nothing to any other
# machine — including a `remo web` service running elsewhere.
#
# Register your MAC's name instead. OrbStack forwards a port the VM listens on
# to the Mac and, with `machines.expose_ports_to_lan` on (the default), exposes
# it on every interface — so `<your-mac>:22` reaches the VM's sshd from your
# LAN, and over a VPN like Tailscale, with nothing installed in the VM.
# Verified end-to-end: a remote host connecting to the Mac's port 22 gets the
# VM's SSH banner, not macOS's.
#
# Two consequences worth knowing before you pick a name:
#
# * The VM's :22 occupies the MAC's :22. Only one VM can own it, and it
# collides with macOS Remote Login. For a second VM, change `Port` in the
# sshd drop-in below and register `remo add name remo@<mac>:<port>`.
#
# * A Mac does not register itself in your router's DNS the way a Linux DHCP
# client does. macOS sends the DHCP hostname option only when `HostName` is
# set, and it is unset by default — `scutil --get HostName` says "not set",
# while `LocalHostName` (the mDNS `.local` name) is never sent. So the
# router has no name for your Mac, and mDNS `.local` will not help: Linux
# hosts typically lack avahi/nss-mdns and cannot resolve it. Fix it once:
#
# sudo scutil --set HostName <name> && sudo ipconfig set en0 DHCP
#
# After that the Mac is registered like any other DHCP client and its
# address may change freely — DNS follows it, so no static IP or reservation
# is needed.
#
# Prefer a bare name over an FQDN or an IP. A bare name resolves through
# whichever search domain is available — your VPN's when it is up, your
# router's when it is not — so one registry entry keeps working as you move.
# ---------------------------------------------------------------------------
# EDIT THIS: the public key of the workstation that will run `remo`.
# ---------------------------------------------------------------------------
# If remo runs on this same Mac, that is ~/.ssh/id_ed25519.pub.
# Leave the placeholder in place and cloud-init keeps password auth enabled
# rather than locking you out (see the guard in runcmd).
#
# The key is installed here, by cloud-init, at account-creation time — NOT from
# runcmd. That is what makes it deterministic: the account is created by this
# file, so there is no "find the right user" step to get wrong.
users:
- name: remo
uid: 1000
shell: /bin/bash
# `remo configure` probes `sudo -n true` up front rather than failing
# halfway through installing packages and system services.
sudo: ALL=(ALL) NOPASSWD:ALL
ssh_authorized_keys:
- ssh-ed25519 AAAA_REPLACE_WITH_YOUR_PUBLIC_KEY workstation
# Declaring `users:` also suppresses the image's own default account, which is
# what would otherwise be sitting on UID 1000.
package_update: true
packages:
# Ansible needs a Python 3 interpreter on the target. ssh_configure.yml
# probes for it with `raw` and fails with an actionable message if absent,
# but there is no reason to make you see that message.
- python3
# hwclock. `community.general.timezone` — the first task in remo's shared
# role list — hard-fails with 'Failed to find required executable "hwclock"'
# without it, and on Ubuntu 24.04+ it lives in util-linux-extra, which minimal
# images do not install. Found the hard way while testing this feature.
- util-linux-extra
- openssh-server
# remo's configure play installs rsync itself, but having it up front means
# `remo cp` works the moment the host is registered.
- rsync
# ---------------------------------------------------------------------------
# SSH port
# ---------------------------------------------------------------------------
# 22 is right when remo runs on this Mac: the VM gets its own IP that macOS can
# reach directly, so nothing needs forwarding.
#
# Change it if you are reaching this VM from somewhere else (e.g. your homelab
# box) via a forwarded port — remo stores the port per host and threads it
# through `remo shell`, `remo configure` and `remo web push`. Register it with
# remo add mbp remo@<host>:<port>
# Note this is NOT OrbStack's own SSH (127.0.0.1:32222, Mac-local only); this
# is a normal sshd inside the VM, which is what remo drives.
write_files:
- path: /etc/ssh/sshd_config.d/10-remo.conf
permissions: '0644'
content: |
# Managed by cloud-init for remo. Ubuntu's sshd_config Includes this dir.
Port 22
PubkeyAuthentication yes
runcmd:
# Harden SSH only once a real key is in place. The key itself was installed
# by the `users:` block above; all this does is decide whether turning
# passwords off is safe.
- |
set -eu
KEY='ssh-ed25519 AAAA_REPLACE_WITH_YOUR_PUBLIC_KEY workstation'
case "$KEY" in
*REPLACE_WITH_YOUR_PUBLIC_KEY*)
# Refuse to harden SSH when no real key was supplied — disabling
# password auth here would leave the VM unreachable over SSH.
echo "remo-cloud-init: placeholder key not replaced; leaving password auth as-is" >&2
exit 0
;;
esac
echo 'PasswordAuthentication no' > /etc/ssh/sshd_config.d/20-remo-hardening.conf
- systemctl enable --now ssh
- systemctl restart ssh
final_message: |
remo-ready after $UPTIME seconds.
The `remo` account exists at UID 1000 with your workstation key. The account
named on `orb create -u …` (UID 501) is OrbStack's own integration account —
ignore it; it is not the one to register.
From the workstation running remo:
remo add mbp remo@<this-vm-ip> --verify # add :PORT if you changed it
remo configure mbp
remo web push # if you use the web console
Do not pass `--skip docker` to configure: the shared role list adds the user
to the docker group, which only exists if the docker role ran.
Devcontainer builds need extra work on OrbStack — Docker in here is nested,
and the kernel refuses the overlayfs mounts BuildKit wants. `remo configure`
handles it (a native-snapshotter builder plus a `devcontainer` shim); builds
are slower, and `apt` inside a running container still cannot work. See
docs/nested-overlayfs.md.