Install Shipwick on a server
This page is for whoever administers the server. It covers the installer, what it puts on the machine, the API token, DNS and firewall, and the ways to install without it.
Before you begin
You need:
- A Linux server, and root on it.
- Docker, installed and running, with the Compose plugin. The installer does not install Docker; that decision belongs to the server's owner. If Docker is missing, the installer stops and points you to
curl -fsSL https://get.docker.com | sh. curlorwget.- Ports 80 and 443 free on the server and reachable from the internet. Automatic HTTPS depends on them, so Shipwick cannot share a server with another web server, reverse proxy or deployment platform that holds them. The installer checks this first and changes nothing if a port is taken.
- Optionally, two DNS names that point at the server: one for the API, one for the dashboard. Every application you give a
domainlater needs a DNS record too.
Run the installer
On the server, as root:
curl -fsSL https://get.shipwick.com | shThe installer asks two questions. Both are optional; press Enter to skip either.
| Question | Stored as | Effect |
|---|---|---|
| Hostname for the API, used by the shipwick CLI | SHIPWICK_AGENT_DOMAIN | The agent's API is served over HTTPS at this hostname, through Caddy |
| Hostname for the dashboard | SHIPWICK_DASHBOARD_DOMAIN | The dashboard is served over HTTPS at this hostname, through Caddy |
Give bare hostnames such as agent.example.com: no https://, no port, no path. The two must be different. Hostnames are validated before anything is written.
Without a terminal, the installer asks nothing and takes the hostnames from the environment:
curl -fsSL https://get.shipwick.com | SHIPWICK_AGENT_DOMAIN=agent.example.com SHIPWICK_DASHBOARD_DOMAIN=dashboard.example.com shThe output looks like this:
Shipwick installer (shipwick/shipwick@latest)
✓ Docker 29.8.0 with Compose 5.5.1
✓ Installed /opt/shipwick/compose.yml
✓ Wrote /opt/shipwick/.env
✓ Started the Shipwick services
✓ The agent is healthy
✓ Installed the shipwick CLI to /usr/local/bin/shipwick
Shipwick is running.
API token (also in /opt/shipwick/.env — it is root on this server, treat it so):
<64 hexadecimal characters>
From your laptop or CI: shipwick login --url https://agent.example.com
Dashboard: https://dashboard.example.com
Open ports 80 and 443 (and 443/udp) — and nothing else — in your firewall.
Upgrade later by running this installer again.What the installer does
- Checks for Linux, root, a running Docker and the Compose plugin.
- Writes
/opt/shipwick/compose.yml. This is the release'scompose.production.yml, in which both Shipwick images are pinned to the release's version. The file is verified against the release'schecksums.txtbefore it replaces anything. - On the first run only, writes
/opt/shipwick/.envwith a freshly generated API token and the two hostnames. IfSHIPWICK_WEBHOOK_URLorSHIPWICK_WEBHOOK_SECRETis set in the environment of that run, it is written there too, so that an upgrade does not lose it. The file has mode0600and the directory0700. - Pulls the images, starts the services, and waits for the agent to report healthy.
- Installs
shipwickto/usr/local/bin, verified the same way. A checksum mismatch installs nothing and leaves a running installation as it was. - Prints the token and the next steps.
Three containers run afterwards, defined in /opt/shipwick/compose.yml:
| Service | What it is |
|---|---|
agent | The Shipwick agent. It has the Docker socket mounted and publishes no port: the only ways in are Caddy and the server itself. |
caddy | The reverse proxy. It publishes ports 80 and 443 (TCP) and 443 (UDP), and obtains and renews certificates on its own. |
dashboard | The web dashboard. It is reached only through Caddy, at the dashboard hostname, and has no credentials of its own. |
State lives in Docker volumes: the agent's SQLite database shipwick.db and its encryption.key in agent-data, certificates in caddy-data. The agent creates encryption.key on its first start and encrypts every deployment's env values with it before they are written to the database; without the key the database cannot be read, and the agent refuses to start against it. Back up encryption.key together with shipwick.db, back up caddy-data, and do not delete either volume casually.
The installer accepts these environment variables:
| Variable | Default | |
|---|---|---|
SHIPWICK_VERSION | latest | Release to install |
SHIPWICK_AGENT_DOMAIN | — | Hostname for the API; asked for when run in a terminal |
SHIPWICK_DASHBOARD_DOMAIN | — | Hostname for the dashboard; likewise |
SHIPWICK_INSTALL_DIR | /opt/shipwick | Where compose.yml and .env are written |
SHIPWICK_BIN_DIR | /usr/local/bin | Where shipwick is installed |
SHIPWICK_WEBHOOK_URL | — | Where the agent posts notifications: a Slack or Discord webhook, or any HTTPS endpoint. Kept in .env when given on the first run; see Get notified |
SHIPWICK_WEBHOOK_SECRET | — | Signs each notification, so your endpoint can tell it came from the agent. Likewise |
Both webhook variables can also be added to /opt/shipwick/.env later, followed by cd /opt/shipwick && docker compose up -d.
The API token
The installer generates the token and prints it once, in the run that created it. It is also in /opt/shipwick/.env.
This is the root token: it has the admin role, its name is root, and it is the one to keep for yourself. Every other token is created from it with shipwick token create, named and given a role — read sees everything, deploy also deploys, rolls back, stops and starts, admin also deletes applications and manages tokens. Give CI a deploy token and put the root token in a password manager. See Create tokens for CI and teammates.
An admin token is root on the server
The agent controls the Docker daemon, and whoever controls the Docker daemon controls the host. Treat the root token, and every admin token, like root SSH access to the server: keep it in a password manager, and keep /opt/shipwick/.env private.
The agent itself keeps only the SHA-256 of each token. Read Security for the full picture.
DNS and firewall
Point DNS at the server for the API hostname, the dashboard hostname, and the domain of every application you deploy. Caddy obtains a certificate for a hostname once its DNS record resolves to the server and ports 80 and 443 are reachable.
In your firewall, open ports 80 and 443 (and 443/udp, for HTTP/3), and nothing else. The agent's own port, 9000, speaks plain HTTP and must never be exposed to the internet.
If you skipped the API hostname, the API is not exposed at all. See Reach the API without a hostname.
Install a specific version
Everything the installer fetches comes from one release — never from a branch — and each file is verified against that release's checksums. By default that is the latest release. To choose one:
curl -fsSL https://get.shipwick.com | SHIPWICK_VERSION=v0.3.0 shBecause the images are pinned in the compose file, a server runs the version it installed until you run the installer again. That is also how you upgrade.
Other ways to install
The compose file, by hand
The installer's setup is one file, configs/compose.production.yml, plus a .env next to it:
SHIPWICK_AGENT_TOKEN=<output of: openssl rand -hex 32>
SHIPWICK_AGENT_DOMAIN=agent.example.com
SHIPWICK_DASHBOARD_DOMAIN=dashboard.example.com
SHIPWICK_WEBHOOK_URL=https://hooks.slack.com/services/... # optionaldocker compose -f compose.production.yml up -dGenerate the token yourself, as shown. The token must be at least 16 characters. If you let the agent generate one, it prints it to its log, and under Docker that log stays readable through docker logs for as long as the container exists. On its first start the agent also creates encryption.key in its data directory; back it up together with the database, or manage the key yourself with SHIPWICK_ENCRYPTION_KEY (64 hexadecimal characters).
The compose file attached to a release pins both images to that release. The copy in the repository refers to latest.
From source
Build the images on the server from a checkout of the repository, then run the installer from that checkout. It uses the compose file next to it instead of downloading one.
docker build -t ghcr.io/shipwick/agent .
docker build -t ghcr.io/shipwick/dashboard dashboard/
sh scripts/install.shBuild the CLI with make build.
A plain binary, next to a Caddy on the host
The agent also runs as a plain binary on Linux, built with make build, next to a Caddy installed on the host. Point the agent at Caddy's admin endpoint:
SHIPWICK_CADDY_ADMIN=http://127.0.0.1:2019The agent listens on 127.0.0.1:9000 by default and keeps its data — shipwick.db and encryption.key — in /var/lib/shipwick. All variables are listed in Agent configuration.
What's next
- Install the CLI on your laptop.
- Deploy your first application.
- Create tokens for CI and teammates instead of handing out the root token.
- Open the dashboard.