Running the server.
Each user on a host runs their own osewa server, as that user. It listens on one port, 7322 by default, and starts a process per session. osewa login --service sets all of this up; this page is for changing it.
As a service
osewa service install # start now and at every login or boot
osewa service install --listen :9000 # the same, on another port
osewa service uninstall # stop it and remove the unitA service restarts the server if it crashes and starts it again after a reboot.
| Linux | macOS | |
|---|---|---|
| Manager | systemd, user unit | launchd, user agent |
| File | ~/.config/systemd/user/osewa.service | ~/Library/LaunchAgents/dev.osewa.server.plist |
| Status | systemctl --user status osewa | launchctl print gui/$(id -u)/dev.osewa.server |
Linux: enable lingering. systemd stops a user's services when they log out, unless lingering is on. On a server you reach only over ssh, run this once:
loginctl enable-linger $USERRunning service install again rewrites the unit with the new flags and restarts the server. A server started with --daemon is stopped first.
Without a service manager
osewa server --daemon detaches into the background, waits until the server answers, and reports:
$ osewa server --daemon
osewa server: started (pid 4821, [::]:7322, log /home/me/.local/state/osewa/server.log)It won't come back after a reboot. If a server is already running, it says so and leaves it alone. Plain osewa server runs in the foreground, logging to the terminal.
Only one server runs per user. A second one fails with osewa server: already running (pid N).
Server flags
These go after osewa server or osewa service install. There is no config file.
| Flag | What it does |
|---|---|
--listen :7322 | The address and port. TCP and UDP use the same number. :PORT listens on every interface, IPv6 and IPv4. |
--name N | The name the server gives itself. Defaults to the hostname. |
--no-quic | Don't listen on UDP; clients use the TLS WebSocket only. |
--no-compress | Don't compress what goes to clients over the WebSocket. |
--no-forward | Refuse port forwards. |
--no-exec | Refuse commands without a terminal. This also stops osewa update from working. |
Changing the port
login always records port 7322, so after moving the server, log in again with --addr to point your machine at the new port:
# on the host
osewa service install --listen :9000
# on your machine
osewa login --service --addr devbox.example.com:9000 me@devboxSessions survive the move: they don't live in the server. Do the second step on every device that uses the host.
If 7322 is blocked where you are and only common ports get through, binding 443 needs root. Instead, keep osewa on a high port and redirect 443 to it with the host's firewall.
Firewalls
Open the port for TCP and UDP. With only TCP open, everything works over the TLS WebSocket, but each connection takes about 300 ms longer while QUIC is tried first, and you lose QUIC's separate streams. If the UDP port can't be bound, the server logs osewa server: no QUIC: listen udp ... and serves TCP alone.
Updating
Update a host from your machine, over osewa, without ssh:
osewa update devbox
copied osewa (linux/amd64) to devbox
devbox's server restarted with itIt copies your build of osewa to the host's ~/.local/bin/osewa, checks its hash, and restarts the server with it. Sessions keep running across the restart, and your attached windows reconnect. If the new build has a different protocol or snapshot version, older sessions keep running but can't be attached any more; see Sessions. The host gets the build for its own platform, found the same way as at login.
A server started with --daemon comes back from an update with default flags: a custom --listen is lost. Run it as a service to keep its flags.
Your machine and the host must run compatible builds: the same protocol version and the same snapshot version (they may link different libghostty-vt commits). When they don't, commands fail with update osewa on the host or here.
Auto-update
A released osewa keeps itself up to date from the GitHub releases, unless you turn it off:
- On your machine, after a command run in a terminal, osewa checks at most once a day, in the background. A newer release that works with this one is installed over it; you get it from the next command.
- A server run as a service or with
--daemonchecks every hour. It installs a newer release that works with this one, waits until no port forward or command is running (a restart would end them; sessions survive it), and restarts into it. Attached windows reconnect. - A release that can't talk to this one (another protocol or snapshot version) is never installed by itself: it would leave every running session unattachable and lock out devices still on this build. osewa says it's out, after commands and in the server log. Update everything together when you're ready:
osewa updatehere, thenosewa update <host>.
osewa set auto-update ask only tells you about releases; osewa set auto-update off stops checking. A host's setting is its own: run it there. OSEWA_AUTO_UPDATE=off in the environment overrides the setting. Builds from source never update themselves.
Logs
| Started as | Log |
|---|---|
| Linux service | the journal: journalctl --user -u osewa |
| macOS service | ~/.local/state/osewa/server.log |
--daemon | ~/.local/state/osewa/server.log |
| foreground | the terminal |
$XDG_STATE_HOME, when set, replaces ~/.local/state.