Yack virtual office

Installing Yack

Introduction

Yack runs on Docker, on one of these:

Both start from the same files (Common resources). After the destination-specific instructions, the remaining sections in this guide apply generally.

Common resources

A handful of loose files, such as the docker-compose definitions and the bin/ scripts that start, stop and manage Yack, are shipped inside the yack image, so each release carries its own. To extract them, with Docker and bash on your own machine (on AWS, the one you install from; otherwise the host Yack runs on), in a new directory, called <INSTALL_DIR> below:

mkdir yack && cd yack    # this is <INSTALL_DIR>, e.g. ~/yack
id=$(docker create --pull=always thoughtbreak/yack:stable) && docker cp "$id:/opt/yack-dist/." . && docker rm "$id"

Every command in this guide runs from <INSTALL_DIR>, and every relative path in it is relative to <INSTALL_DIR>. On AWS there are two: yours, on the machine you install from, and each host's, ~/yack, which the install makes.

On AWS

You need Docker and AWS credentials on your machine, a Route 53 hosted zone, an EC2 key pair and a sign-in client (In detail lists them).

TL;DR

In <INSTALL_DIR>, with the common resources extracted (above):

# Optional: the IAM policy for a provisioning user of your own, for an administrator to attach
./aws-bootstrap.sh --policy --app your-org-yack --region eu-west-2 > your-org-yack-provision-policy.json

# Once per AWS account and region, as an administrator
./aws-bootstrap.sh --region eu-west-2

# Your settings: copy the template, then edit .env as its opening comments
# say - set REALM, a sign-in client and, in its "On AWS" section, AWS_REGION,
# YACK_ADMIN, AWS_KEY_PAIR and AWS_APP (AWS_ZONE too when your Route 53
# hosted zone isn't REALM less its first label); change anything else you want to
cp .env.example .env

# Provision AWS and install Yack (aws/prod remembers the deployment's settings after)
./aws-install.sh prod

# Optional: demo data, over ssh through Systems Manager (see In detail for ~/.ssh/config)
ssh yack.example.com 'cd yack && bin/bootstrap-demo.sh jo@example.com'

In detail

One command, run on your own machine, provisions Yack's AWS stacks and installs Yack on them: ./aws-install.sh. It uses the thoughtbreak/yack-provision image matching the selected release, which carries the stacks and the tools to deploy them. For one deployment, <ENV> (e.g. prod), it makes three stacks:

You need, in the account and region you choose:

With these files copied out of the image on your machine (above), copy <INSTALL_DIR>/.env.example to <INSTALL_DIR>/.env and edit it as its opening comments say. Then run ./aws-bootstrap.sh (once per account and region) and ./aws-install.sh, as in the TL;DR.

Both scripts, with no arguments, explain their options; --profile picks an AWS CLI profile. ./aws-install.sh reads .env, or --settings <FILE>: the deployment's settings (AWS_REGION, YACK_ADMIN, AWS_KEY_PAIR, AWS_APP, AWS_ZONE, AWS_HOSTS, AWS_INSTANCE_TYPE, AWS_BATCH) as well as Yack's, each explained there; an option of the same meaning (--region, --admin ...) overrides one for that run. AWS_APP prefixes every name (default yack); bucket names are global, so choose your own. CDK asks before creating IAM roles; answer y. YACK_ADMIN is your first superadmin, activated by their first sign-in.

./aws-install.sh saves your .env settings, and the secrets it generates, in AWS Systems Manager Parameter Store under /<APP>/<ENV>/env/. It installs Yack into ~/yack on each host (its <INSTALL_DIR>), with timers for backups, certificate renewal and upgrades, starts it and makes the superadmin. Each host keeps the install's log in ~/yack/install.log.

Your settings live in AWS; <INSTALL_DIR>/.env on your machine is your copy of them, and the one place you change them. Four things to know:

<INSTALL_DIR>/aws/<ENV> remembers the deployment's settings (AWS_ZONE, AWS_KEY_PAIR ...), and Parameter Store the secrets, so nothing is generated twice. It leaves an installed host's release to its upgrades; --reinstall copies this release over it. Files you put in <INSTALL_DIR>/aws/<ENV>/local/ reach each host's ~/yack/local/: local/demo-users.csv adds your own people to the demo dataset (see Loading data). A directory is one deployment's, and a deployment can't change between one host and three in place.

To ssh to a host, Systems Manager stands in for an open port. With the AWS CLI's Session Manager plugin installed, add an entry per host to ~/.ssh/config, with HostName the instance id from YackHostsStack-<ENV>'s outputs (HostInstanceId, or HostAInstanceId ... with three hosts):

Host yack.example.com
  HostName i-0123456789abcdef0
  User ec2-user
  IdentityFile ~/.ssh/your-org-yack.pem
  ProxyCommand sh -c "aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters portNumber=%p"

./aws-install.sh does everything that you would do on your own host: settings, domain, certificate, start, timers and superadmin.

On your own host

Run everything from <INSTALL_DIR>, and always use its bin/ scripts rather than calling docker compose directly — they source bin/env.sh, which derives a few settings (e.g. DATABASE_URL, JANUS_API_URL) from your .env that plain docker compose up won't compute on its own. The certificate (2. Get a TLS certificate) is the one exception, run with bin/env.sh sourced.

TL;DR

You need a Linux host or an Apple Mac with Docker (on a Mac, Docker Desktop with 12 GB of memory), a domain pointing at it, every port in Prerequisites reaching it, and a sign-in client: Google's, Microsoft's or both (Sign-in providers). Details in 1. Configure to 4. Make yourself a superadmin, and for a Mac, Mac specifics.

In <INSTALL_DIR>, with the common resources extracted (above):

# Your settings: copy the template, then edit .env as its opening comments say.
# Without AWS you also set REALM, LETSENCRYPT_EMAIL, the secrets (random
# strings: openssl rand -base64 48) and ATTACHMENTS_UNSCANNED=true (no S3 to
# scan uploads); on a Mac also UPGRADE_ENABLED=false, and PUBLIC_HTTP_PORT if
# the router forwards port 80 to another port
cp .env.example .env

# Once you've set REALM and the rest in .env, fit the config to your domain:
(. bin/env.sh && bin/localise.sh)

# A certificate, then Yack, then yourself as its superadmin
(. bin/env.sh && docker compose -f docker-compose-certbot.yml up --abort-on-container-exit)
bin/start.sh
bin/add-superadmin.sh you@example.com

# On Linux: timers for certificate renewal, backups and upgrades (uses sudo)
bin/install-timers.sh

On Linux, Yack then renews its certificate, backs up and upgrades itself. On a Mac, upgrade with bin/upgrade-local.sh, and renew the certificate with bin/renew-cert.sh every couple of months.

Prerequisites

1. Configure

On a host of your own, in <INSTALL_DIR>, with the common resources extracted (above):

cp .env.example .env

Required settings in .env read VAR=${VAR:?message}; replace each with a literal value, or leave it and export the value yourself (shell profile, systemd EnvironmentFile, secrets manager). Anything missing stops the bin/ scripts with an error naming it.

The required values, and where they come from:

Database

MongoDB runs as MongoDB Community Edition with mongot, MongoDB's search service, as two containers (docker-compose-mongo.yml); mongot needs MONGOT_PASSWORD. The data lives in <INSTALL_DIR>/data/dbs/prod/, which <INSTALL_DIR>/data/dbs/current links to. Keep the disk well under 90% full: around there mongot pauses building search indexes, leaving message search and @Yack without results.

Your domain

The nginx and coturn config ship with thoughtbreak.com as a placeholder domain. With REALM set, fit them to it (./aws-install.sh does this for you):

(. bin/env.sh && bin/localise.sh)

2. Get a TLS certificate

Before starting Yack for the first time, obtain a Let's Encrypt cert for REALM (this needs port 80 reachable from the internet):

(. bin/env.sh && docker compose -f docker-compose-certbot.yml up --abort-on-container-exit)

This writes the certificate under <INSTALL_DIR>/etc/letsencrypt/live/<REALM>/, which the nginx and TURN configs already point at.

Renewals: bin/renew-cert.sh re-runs certbot and reloads nginx. On Linux, run bin/install-timers.sh (it uses sudo) to install the systemd timers that renew daily, back up every 6 hours (Backups) and carry out upgrades (Upgrades); ./aws-install.sh runs it for you. A Mac has no timers (Mac specifics).

3. Start Yack

bin/start.sh

This brings up mongo, mongot, janus, turn, nginx, the pii and media-processing sidecars, and the yack app itself. Check . bin/env.sh && dockercompose ps to confirm everything is healthy.

Stop with bin/stop.sh, restart with bin/restart.sh.

4. Make yourself a superadmin

Make yourself a superadmin, so you can sign in and administer Yack - the account activates when you first sign in, and takes its name from the address (jo.bloggs@ is Jo Bloggs):

bin/add-superadmin.sh you@example.com

Mac specifics

Yack runs on one Apple Mac with Docker Desktop, as on a Linux host: its images are built for arm64 too, and on macOS bin/env.sh adds docker-compose-mac.yml, which publishes Janus's and coturn's ports rather than using Linux host networking. Follow 1. Configure onwards, in an <INSTALL_DIR> of its own, with these differences:

Sign-in providers

People sign in with Google, with Microsoft (personal accounts, and work or school accounts), or with either: the welcome page offers each provider whose client is set. An admin adds each person by email address. The first sign-in links that provider's account to them, provided the provider has verified the address; later sign-ins find them by that account, and keep their email in step with the provider's. Admins can unlink an account in Manage users, for someone who changes accounts.

Google: in Google Cloud Console, APIs & Services, create an OAuth 2.0 Client ID (Web application) with authorized redirect URI https://<REALM>/auth/google/callback (add :<PUBLIC_YACK_PORT> if not 443), and set GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET.

Microsoft (free with Microsoft Entra ID; any Azure account has a tenant): at entra.microsoft.com, App registrations, New registration:

Set MICROSOFT_CLIENT_ID (the Application (client) ID) and MICROSOFT_CLIENT_SECRET (the secret's value). MICROSOFT_TENANT (default common) narrows who may sign in: organizations (work or school only), consumers (personal only), or one directory's tenant id (only its people).

Out of office from Google Calendar

People can have their out of office come from their Google Calendar's out-of-office events instead of booking it in Yack, each choosing on the Out of office page. Yack reads only those events' times, never their titles, with each person's consent. It needs Google sign-in (above), on the same client:

Google tells Yack of changes at https://<REALM>/webhooks/google-calendar; Yack also checks every 30 minutes, which is all an installation Google can't reach over HTTPS gets.

Loading data

With Yack running and yourself its superadmin, load if you like the bundled synthetic demo dataset, or your own users and teams (on AWS, over ssh: On AWS, In detail):

# Demo data, with one real admin account (and any people of your own listed
# in <INSTALL_DIR>/local/demo-users.csv, in users.csv's columns, alongside the demo's):
bin/bootstrap-demo.sh you@example.com   # then embeds its chat, so @Yack can draw on it

# Your own data, from CSV files anywhere on the host:
bin/bootstrap-users.sh teams.csv users.csv

teams.csv has the columns name,type,door_policy (type core or task; door policy open, knock or locked, default knock); users.csv has name,email,team,role,extra_teams (team the user's core team; role user, admin or superadmin, default user; extra teams separated by ;). Both are safe to re-run: teams match by name and users by email.

Stopping and starting

On AWS, ./aws-install.sh NAME --stop stops the installation's hosts, for when it isn't needed for a while: their disks, the database, your settings and its address are kept, and the hosts' compute is no longer charged (the load balancer, addresses and disks still are). --start starts them again and waits until Yack answers. In case of trouble, --restart does both: the hosts turned off and on again, on fresh hardware.

Logs and support

On AWS, every host's logs go to CloudWatch Logs in your account, in the log group /yack/<env> (or your --app in place of yack), one stream per host and service, where Logs Insights searches them all at once. They can hold personal data (names, sign-in email addresses, rooms), so they're kept 30 days, then deleted; RETENTION_LOGS in .env changes that (applied by ./aws-install.sh). Elsewhere, each host keeps its own: dockercompose logs.

Thoughtbreak's support has no access to your installation unless you grant it, and then only what you grant, in your account, with every use in your CloudTrail. In .env, then ./aws-install.sh:

SUPPORT_ACCESS=logs                 # read this installation's logs; or shell, to
                                    # also open sessions on its hosts, each recorded
                                    # to the /yack/<env>/sessions log group
SUPPORT_ACCESS_ACCOUNT=123456789012 # Thoughtbreak's AWS account, which we give you
SUPPORT_ACCESS_UNTIL=2026-12-31     # optional: it ends after this day

SUPPORT_ACCESS=off and ./aws-install.sh revoke it, as does deleting the role yack-<env>-support in the IAM console.

Without AWS, run this on the host and send us the file it writes: each service's log (by default the last 24 hours), the release and the services' state, and the names, never the values, of your settings:

bin/support-bundle.sh [--since 24h]

Upgrades

The Release notes say what each release brings.

Yack upgrades itself. When the release tagged stable on Docker Hub changes, the app plans an upgrade for your window (23:00-02:00 UTC by default), with at least half an hour of it left and at a moment when nobody is publishing audio or video and no recording is unfinished, and the yack-upgrade timer (bin/install-timers.sh) carries it out: it pulls the new images, backs up, stops Yack and saves its database, swaps the release's files into <INSTALL_DIR> (never .env, data/ or etc/letsencrypt/), restarts and checks Yack answers, rolling back if it doesn't.

Every upgrade is a short outage, usually a minute or two. Some releases also migrate the database, after which older releases refuse to start on it; if such a release fails, the rollback restores the database saved just before it, losing anything written in between (nobody can use Yack then anyway). The saved database stays in <INSTALL_DIR>/.upgrade/db.archive.gz until the next upgrade. Superadmins get a message with the outcome, including any new settings to consider (described in .env.example); Upgrades in the settings menu shows the latest. A new setting always has a default, and a feature needing a new secret stays off until you set it.

Yack never moves to an older release than it runs. On AWS, to upgrade now rather than wait for the window (even with upgrades off), or to a particular release, from <INSTALL_DIR> on the machine you installed from:

./aws-upgrade.sh prod [--release main-180]

It upgrades just as above, though not during a call or an unfinished recording, and follows the upgrade until it ends.

The timer needs to run bin/install-timers.sh with passwordless sudo to refresh timers a release changes; without it, the upgrade notes that you should run it yourself.

Where nothing upgrades unattended (a Mac, or UPGRADE_ENABLED=false), one host upgrades by hand, in the same way and with the same rollback:

bin/upgrade-local.sh [main-190]   # stable's release by default

It pulls the release's images (refusing ones not built for this machine, or an older release than this one), backs up if BACKUP_TARGET is set, stops Yack and saves its database to <INSTALL_DIR>/.upgrade/db.archive.gz, swaps the release's files in (keeping the replaced ones in <INSTALL_DIR>/.upgrade/previous), restarts and waits for Yack to answer; if it doesn't, the files, and the database if it was migrated, go back and the old release restarts. It doesn't run the release's upgrade/run.sh, which is for Linux hosts.

Backups

Set BACKUP_TARGET in <INSTALL_DIR>/.env to an s3:// bucket or a directory, then bin/backup.sh runs every 6 hours from the yack-backup timer (bin/install-timers.sh): it writes a gzipped mongodump --oplog of the whole instance, an archive of <INSTALL_DIR>/data/uploads and a copy of .env, stamped with the time. On AWS, BACKUP_TARGET is the backups bucket, where they expire after 14 days; otherwise expire old backups yourself, e.g. with a bucket lifecycle rule, since they hold personal data. .env holds every secret the installation needs, so encrypt the bucket (or keep the directory private: backups there are written readable only by their owner).

bin/restore.sh [<STAMP>] restores the database and uploads from the latest backup, or the one named, after asking; Yack recreates its search indexes when it restarts. It leaves .env alone, so a backup can be restored onto another host. bin/restore.sh --env [<STAMP>] restores only .env, keeping the current one as <INSTALL_DIR>/.env.before-restore-<time>. To rebuild a lost host: extract the common resources into a new <INSTALL_DIR>, write a .env there with just REALM and BACKUP_TARGET, run bin/restore.sh --env, then bin/start.sh and bin/restore.sh.