Skip to content
EntryWick documentation

For whoever installs EntryWick on their organization's own server.

Installing a self-hosted EntryWick (week 21)

From a new Ubuntu 24.04 server to signing in as the Owner, in order. Every command is meant to be copied as it is; the only things to change are the domain, the IP address and the release number, shown as events.example.org, 203.0.113.10 and 1.0.0. The target is under 15 minutes from the first SSH login. PRICING_ENTITLEMENTS §5, ADR-019, ADR-020. What each command does and refuses: cli.md.

Who opens it: whoever installs EntryWick on their organization's own server.

What they came to do: get a running, licensed instance and sign in to it.

What must be true when they leave: EntryWick answers on https at the organization's address, the Owner can sign in, the instance runs a release EntryWick signed for the license's channel, and a copy of .env is in their password manager.

Before you start

  • A server that meets requirements.md: Ubuntu 24.04 LTS on amd64, 2 vCPU and 4 GB for events of up to 2,000 attendees (4 vCPU and 8 GB up to 10,000), 20 GB free disk (40 GB recommended), and its public IPv4 address. Nothing else installed on it.
  • A domain for EntryWick whose DNS you can change, such as events.example.org.
  • The license key EntryWick sent you. It starts with ew_lic_ and is one long line. It names your organization and your update channel (stable or beta).
  • The release to install, such as 1.0.0 — sent with the key, or the newest release on your channel.
  • For the Owner: a name, an email address, and a password of 12 characters or more that is not in a known breach.

1. Point the domain at the server

At your DNS provider, create two A records (use your domain and the server's address):

events.example.org.     A   203.0.113.10
*.events.example.org.   A   203.0.113.10

Do this first: the records often take a few minutes to be seen everywhere, and certificates can only be issued once they are. If the domain has AAAA records, point them at the same server or remove them.

2. Log in as root

ssh root@203.0.113.10

If your provider gave you a user with sudo instead, log in as that user and run sudo -i. Every command below runs as root. Check that the records from step 1 already reach this server (both should print its address):

getent hosts events.example.org
getent hosts check.events.example.org

If they print nothing yet, carry on; check again before step 8.

3. Open the firewall (only if one is on)

ufw status

If it says Status: inactive, skip this step. If it is active:

ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow 443/udp

If your provider has a firewall in its control panel, allow the same ports there (22, 80 and 443 over TCP, 443 over UDP).

4. Install Docker

Docker's own packages for Ubuntu 24.04, as Docker documents them:

apt-get update
apt-get install -y ca-certificates curl
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
EOF
apt-get update
apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

If a screen asks which services to restart, press Enter. Then check (Docker Engine 24 or newer, Compose 2.24 or newer):

docker version --format '{{.Server.Version}}'
docker compose version --short

Docker starts now and on every reboot.

5. Install PHP

entrywick is a PHP program that runs on the server; EntryWick itself runs in its image.

apt-get install -y php8.3-cli
php -v

6. Install the entrywick command

Set the release, then download the tool with its checksum and its signature:

EW_RELEASE=1.0.0
EW_DOWNLOAD="https://github.com/entrywickapp-coder/entrywick/releases/download/v${EW_RELEASE}"
mkdir -p /tmp/entrywick && cd /tmp/entrywick
curl -fsSLO "$EW_DOWNLOAD/entrywick.phar"
curl -fsSLO "$EW_DOWNLOAD/entrywick.phar.sha256"
curl -fsSLO "$EW_DOWNLOAD/entrywick.phar.sigstore.json"

Pending: the download address. Each release's entrywick.phar, entrywick.phar.sha256 and entrywick.phar.sigstore.json are attached to that release on GitHub, at the address in EW_DOWNLOAD above. That repository is not public yet, so today this address cannot be downloaded from; EntryWick will publish a public one (docs/NEEDS_FROM_OWNER.md, week 21). When it does, only the EW_DOWNLOAD= line changes. Until then, use the copy of the three files EntryWick sends you: put them in /tmp/entrywick and continue below.

Check the file is the one EntryWick's release workflow built and signed. The first command prints entrywick.phar: OK, the second Verified OK:

sha256sum -c entrywick.phar.sha256
docker run --rm -v /tmp/entrywick:/w:ro \
  ghcr.io/sigstore/cosign/cosign:v2.6.1@sha256:68839b7f13dac5a6744a5d8818e984dd39183374e37855c19e14d623d9bc9037 \
  verify-blob --bundle /w/entrywick.phar.sigstore.json \
  --certificate-identity "https://github.com/entrywickapp-coder/entrywick/.github/workflows/release.yml@refs/tags/v${EW_RELEASE}" \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  /w/entrywick.phar

If either fails, stop: do not install that file. Otherwise:

install -m 0755 entrywick.phar /usr/local/bin/entrywick
cd /
entrywick --version

It prints entrywick 1.0.0. That is also the release entrywick install installs.

Pending: reading the image. entrywick pulls ghcr.io/entrywickapp-coder/platform. While that package is private, the server must be signed in to it first: docker login ghcr.io with the read-only token EntryWick gives you. Once it is public, skip this (docs/NEEDS_FROM_OWNER.md, week 21).

7. Have the license key ready to paste

Open it in your password manager or the email from EntryWick. It is pasted once, in the next step, and is not shown on screen as you paste it.

8. Run the installer

entrywick install

It first checks the server. Each line starts ok, warn or FAIL; any FAIL stops it (see Troubleshooting). Then it asks, one at a time (a value in [brackets] is the default: press Enter to take it):

Question What to answer
Domain for EntryWick (organizations get their own name under it) The domain from step 1: events.example.org
Your organization's name As it should appear to people, up to 160 characters
Its address (…events.example.org) The name in front of the domain: riverside gives riverside.events.example.org. 3 to 63 lowercase letters, numbers or inner hyphens. Not one of the names EntryWick keeps for itself, such as admin, api, app, scan, www, mail, support or status
Timezone Where your events happen, such as America/Chicago ([UTC] by default)
Owner's name (the first person to sign in) The person who will own the organization in EntryWick
Owner's email Their email: how they sign in. It is also the address the certificate authority writes to, and the sender of the app's email until you set up mail
License key (ew_lic_…, not shown as you paste) Paste the whole key and press Enter. A key that is cut short is asked for again

It then writes /opt/entrywick/.env (mode 600) with new random database passwords and a new APP_KEY, and works through its stages, each starting with ==>:

  1. checks the signature of the release for your key's channel, and pulls it by the digest that was signed;
  2. takes the Compose files out of that image and starts the database and Redis;
  3. has the app check the license key — a key the app does not accept is asked for once more, then the install stops (exit 7) before any table is created;
  4. creates the database tables and starts EntryWick;
  5. asks the app whether it takes the organization's name, address and Owner — the app knows which addresses EntryWick keeps for itself and which emails already have an account. An answer it refuses is said with the app's reason and asked for again (without a terminal the install stops and names the option to give; the refused answer is not kept). Then it asks for the Owner's password, twice: Password for …@… (12 characters or more, not shown) and The same password again, and creates the organization the key names, with its Owner;
  6. says hello to EntryWick's license server (a warn here is harmless: the instance runs without it);
  7. checks that everything answers, and that the organization's address has a certificate.

Every question can be given as an option instead, and the key and the password from a file: entrywick help install. --version=X.Y.Z installs that release instead of the tool's own (it must be signed for your key's channel).

If the install is cut short (a dropped connection, a failure you then fix), run entrywick install again: it carries on from the stage that did not finish, with the same answers. An option given on the second run replaces the answer kept from the first (except the domain, which is in .env by then, and the release, which is in .env.version).

Done

It ends like this:

EntryWick is installed.
  Sign in:   https://riverside.events.example.org/admin as dana@example.org
  Scanner:   https://scan.events.example.org
  Settings:  /opt/entrywick/.env — copy it to your password manager now
  Mail goes to the log until you set MAIL_MAILER and its settings in .env.
Next: entrywick backup, and entrywick doctor any time.

Open the Sign in address and sign in as the Owner with the password from stage 5. The first visit to each address takes a few seconds longer while its certificate is issued.

9. Right after installing

  1. Save .env. Copy the whole of /opt/entrywick/.env into your password manager (cat /opt/entrywick/.env). Without its APP_KEY, no backup can be read.
  2. Set up email. Open /opt/entrywick/.env (nano /opt/entrywick/.env) and replace the MAIL_ lines with your mail provider's settings, for example over SMTP:
    MAIL_MAILER=smtp
    MAIL_HOST=smtp.example.com
    MAIL_PORT=587
    MAIL_USERNAME=events@example.org
    MAIL_PASSWORD=your-smtp-password
    MAIL_FROM_ADDRESS=events@example.org
    MAIL_FROM_NAME="Riverside Events"
    
    (on port 465 add MAIL_SCHEME=smtps). Then apply it — the app, Horizon and the scheduler restart with the new settings:
    entrywick compose up -d
    
  3. Take the first backup, and schedule the rest: entrywick backup, then the nightly schedule in backup.md.
  4. Check everything: entrywick doctor. It ends All well. (exit 0); a warning (exit 1) says what to look at. Run it again before every event.

Updating later: update.md.

How long it takes

Most of the 15 minutes is Docker installing (step 4) and the images downloading (stage 1 and 2 of step 8); the rest is typing. A slow disk or network makes the downloads longer. Nothing waits on DNS except the certificates, which are issued on the first visit once the records reach the server.

Troubleshooting

Messages start FAIL or warn on a line of their own, or error: at the end. The exit code is in echo $? right after the command.

You see Exit What to do
FAIL Docker Engine is not installed, not running, or this user may not use it. 2 Do step 4, and run entrywick as root (sudo -i). systemctl status docker shows whether it runs
FAIL The Docker Compose v2 plugin is missing (apt install docker-compose-plugin). 2 apt-get install -y docker-compose-plugin
FAIL Docker Engine …: 24.0 or newer is needed / FAIL Docker Compose …: 2.24.0 or newer is needed 2 An older Docker is installed. Remove it (apt-get remove -y docker.io docker-compose docker-compose-v2) and do step 4
FAIL Port 80 is already in use; EntryWick's Caddy serves 80 and 443 … 2 See what holds it: ss -ltnp 'sport = :80'. For Apache or nginx: systemctl disable --now apache2 (or nginx)
FAIL … at least 2 vCPU and 4 GB are needed … 2 A bigger server. For a trial only: entrywick install --skip-requirements
FAIL … GB free: at least 20 GB is needed 2 A bigger disk, or free space. --skip-requirements also skips this
error: No terminal to ask: add --…=…. 2 The installer was run without a terminal (from a script, or ssh with a command). Run it in a normal SSH login, or give every answer as an option (entrywick help install)
error: … is not signed by EntryWick's release workflow for the stable channel, or could not be checked. Nothing was pulled. 5 Usually the server cannot reach ghcr.io or Sigstore (requirements.md, outbound), or the image is still private (the note in step 6). Also when that release was never published on your channel: check the release number with EntryWick
error: … is a beta; this license is on the stable channel. 5 Install a stable release, or ask EntryWick for a key on the beta channel
error: This entrywick build names no release (dev): add --version=X.Y.Z. 2 The tool was not downloaded from a release: do step 6, or name the release: entrywick install --version=X.Y.Z
error: This install was started with … (.env.version); finish it without --version, then entrywick update --to=…. 2 Run entrywick install without --version to finish, then update (update.md)
warn the app refused the slug "…": … (or the organization, admin name, admin email) Give another answer when asked. Without a terminal the install stops with error: Run entrywick install again with --slug=… …: run it again with that option
error: The app did not accept the license key: expired … (or invalid, missing) 7 The key is past its dates, or was not pasted whole. Put the right key on the EW_LICENSE_KEY= line of /opt/entrywick/.env, then entrywick install again
error: The new key is for another update channel. Run entrywick install again to install from it. 7 Run entrywick install again, as it says
error: Creating the organization (ew:instance:organization) failed: then a reason 1 The reason is the app's, and after the check above it is the password: too short, or found in a known breach. Run entrywick install again and choose another
warn no certificate for … yet (…). Point … and *.… at this server; Caddy gets one on the first visit. 0 Check step 1 with getent hosts, and that ports 80 and 443 are open (step 3). Then open the address in a browser; entrywick compose logs caddy shows why a certificate was refused
warn the license server did not answer (…) 0 Nothing to do: the instance runs without it and tries every night (heartbeat.md)
error: EntryWick started but is not healthy yet. Run entrywick doctor, then entrywick install again to finish. 1 Do both. entrywick compose ps lists the containers; entrywick compose logs app (or horizon, mysql) shows why one does not start
error: /opt/entrywick/.env has no APP_KEY. Restore it from your copy, or move it away to start again. 1 .env was edited or cut short. Put back your copy
EntryWick is already installed in /opt/entrywick (since …). 0 It is. Use entrywick doctor, and update.md

Starting a first install again from nothing. Only on a server that has never held real data — this deletes the database and every stored file:

entrywick compose down -v
mv /opt/entrywick /opt/entrywick.failed
entrywick install

Every exit code: cli.md.