Run it for your lab
One lab, one database.
Set-up recipes for BioManager. Pick a route, do its steps in order, and stop at Done when. Most labs pay nothing.
Part one
Start here
Pick a route
- How many people? Just you: A. More than one: question 2.
- Do they need it outside the lab network? (At home, on phones on mobile data, at another site. Your campus VPN counts as inside.) Yes: D, or E if some of them can't install the Tailscale app. No: question 3.
- Does your IT give you a server? Yes: C. No: B.
| Route | Who can reach it | Cost per month | Set-up time |
|---|---|---|---|
| A · One computer | That computer only | $0 | 2 minutes |
| B · Linux computer in the lab | The lab or campus network, and its VPN | $0 with a spare computer (a new small PC is a one-off $300–600) | 1 hour |
| C · University server | The campus network and VPN | Often $0; some IT departments charge | Depends on IT, then 30 minutes |
| D · Cloud VM + Tailscale recommended | Your lab, from anywhere; no one else | $0 (Oracle Cloud Always Free + Tailscale's free plan), or about $5–7 for a paid VM | 1 hour |
| E · Cloud VM + your own domain | Anyone with the address (they still need an account) | As D, plus about $1 for the domain ($10–15 a year) | 1–2 hours |
Prices as charged in September 2026; check before you sign up. Every server route (B–E) includes nightly backups, a weekly restore test and HTTPS.
Set it up with an AI assistant
An AI assistant with a terminal (Claude Code, Cursor, Codex and the like) can follow route B, C, D or E for you
from deploy-with-ai.md, a version of this page written for it. Paste
this to your assistant:
You still create the accounts, approve sign-ins and type every password yourself; the guide makes the assistant stop and ask at each of those.
Part two
Routes
A · One computer: the desktop app
You need
- A Mac (Apple silicon or Intel), a Windows PC, or a Linux PC (x86-64).
- Cost: $0 a month.
- Time: 2 minutes.
-
Download the file for your computer from the Download page.
You should see:
BioManager-macOS-AppleSilicon.zip,BioManager-macOS-Intel.zip,BioManager-Windows.ziporBioManager-Linux.AppImagein your Downloads folder.If not: on a Mac, Apple menu → About This Mac says which chip you have.
-
Open it.
Mac: unzip it, drag BioManager into Applications, then right-click it → Open → Open. Windows: extract the zip, open BioManager.exe, and at the warning choose More info → Run anyway. Linux:
cd ~/Downloads && chmod +x BioManager-Linux.AppImage && ./BioManager-Linux.AppImage
You should see: the BioManager window, asking you to create an account.
If not: a Mac that offers only Move to Trash: System Settings → Privacy & Security → Open Anyway. A Linux AppImage that won't start needs FUSE: install
libfuse2. -
Create your account and answer the set-up questions (user guide).
You should see: BioManager's Home page, with the databases you ticked.
Done when: BioManager opens on Home, signed in as you.
~/Library/Application Support/Biomanager/ (Mac),
%APPDATA%\Biomanager\ (Windows) or ~/.local/share/Biomanager/ (Linux): back that folder
up with Time Machine or File History.A few people on one trusted network can share this computer's lab without a server: Settings → Devices → Share this lab on the network. It has no nightly backup and no encryption (Devices).
B · A Linux computer in the lab
You need
- A Linux computer that stays on (Ubuntu 24.04, or another Linux with systemd), x86-64 or ARM, with 2 CPU cores, 2 GB of memory and 20 GB of free disk. For a Mac, use the desktop app: Settings → Set up a lab server → This computer, for the whole lab.
- An account on it that can use
sudo. - A fixed IP address or DNS name for it, from your IT.
- Cost: $0 a month.
- Time: about an hour.
-
Ask IT for a fixed IP address or DNS name for this computer, and turn off sleep (Ubuntu: Settings → Power → Automatic Suspend → Off). Then check its addresses:
hostname -I
You should see: the IP address IT gave you, among others.
If not: the address changes after a restart: ask IT for a DHCP reservation for this computer.
-
Install Docker.
curl -fsSL https://get.docker.com | sudo sh sudo usermod -aG docker $USER
You should see: Docker's installer finish without an error.
If not:
sudo: a password is requiredornot in the sudoers file: use an account that can usesudo, or ask IT. -
Log out, log in again, and check Docker.
docker compose version
You should see:
Docker Compose version v…If not:
permission denied while trying to connect to the Docker daemon socket: you haven't logged in again since step 2. Log out and in (or restart). -
Download BioManager.
sudo mkdir -p /opt/biomanager && sudo chown "$USER" /opt/biomanager curl -fsSL -o /tmp/biomanager-server.tar.gz \ https://github.com/gaspolymerase/biomanager/releases/latest/download/biomanager-server.tar.gz tar -xzf /tmp/biomanager-server.tar.gz -C /opt/biomanager /opt/biomanager/Biomanager/deploy/host/load-image.sh
You should see:
Downloading BioManager <version> for amd64…(orarm64), thenLoaded image: ghcr.io/gaspolymerase/biomanager:<version>andLoaded. Start or update with: …If not:
No BioManager image for …: BioManager runs on x86-64 and ARM64 only.Could not download: this computer can't reach github.com; ask IT about a proxy, then run the last line again. -
Write the settings that need no choices: a database password, the certificate type and the backup folder.
cd /opt/biomanager/Biomanager/deploy cp .env.example .env && chmod 600 .env sed -i "s|^POSTGRES_PASSWORD=.*|POSTGRES_PASSWORD=$(openssl rand -hex 24)|" .env sed -i "s|^TLS=.*|TLS=internal|; s|^BACKUP_DIR=.*|BACKUP_DIR=/opt/biomanager/backups|" .env
You should see: no output.
If not:
cannot stat '.env.example': step 4 didn't unpack. Run step 4 again. -
Enter your address and time zone. Open the settings file:
nano .env
Change these two lines to read as below, then save with Ctrl+O, Enter and close with Ctrl+X:
DOMAIN=<your-domain> TZ=<your-time-zone>
<your-domain>: the fixed IP address or DNS name from step 1, withouthttps://.<your-time-zone>: likeEurope/BerlinorAsia/Shanghai;timedatectlshows this computer's. With a second disk, also setBACKUP_DIRto a folder on it.You should see:
DOMAIN=near the top of the file,TZ=about halfway down.If not:
nano: command not found:sudo apt-get install nano. -
Check the settings.
grep -E '^(DOMAIN|TLS|TZ|BACKUP_DIR)=' .env docker compose config --quiet && echo "settings ok"
You should see: your four lines, with
TLS=internal, thensettings ok.If not:
set POSTGRES_PASSWORD in .env: run step 5 again.DOMAIN=biomanager.example.edu: the edit wasn't saved; repeat step 6. -
Start BioManager.
docker compose up -d --build
You should see: after a minute or two,
biomanager-db-1,biomanager-app-1,biomanager-caddy-1andbiomanager-backup-1, eachStartedorHealthy.If not:
pull access denied for ghcr.io/gaspolymerase/biomanager: runhost/load-image.sh, then this again.container biomanager-app-1 is unhealthy:docker compose logs --tail 100 appsays why. -
Check that everything runs.
docker compose ps
You should see:
dbandapp(healthy),caddyUp, andbackup(healthy), or(health: starting)for a few minutes while it takes its first backup.If not: a service missing or
Restarting:docker compose logs --tail 100 <service>. -
Get the setup code for the first account.
docker compose logs app | grep "setup code"
You should see:
No accounts yet. Create the first admin at /register with setup code 1a2b-3c4d-5e6f (also saved in /data/setup-code).If not: nothing: the app is still starting. Wait a minute and repeat, or run
docker compose exec app cat /data/setup-code. -
Save BioManager's certificate, for the lab's devices to trust.
docker compose exec caddy cat /data/caddy/pki/authorities/local/root.crt > biomanager-root.crt head -1 biomanager-root.crt
You should see:
-----BEGIN CERTIFICATE-----If not:
No such file or directory: Caddy is still starting. Wait ten seconds and repeat. -
On each computer and phone that will open BioManager, once: copy
biomanager-root.crtto it (email, USB stick, AirDrop) and install it.- Mac: double-click it; in Keychain Access, open it and set Trust → When using this certificate → Always Trust.
- Windows: double-click it → Install Certificate → Local Machine → Place all certificates in the following store → Trusted Root Certification Authorities.
- iPhone, iPad: open it, install the profile in Settings → General → VPN & Device Management, then turn it on in Settings → General → About → Certificate Trust Settings.
- Android: Settings → Security → Encryption & credentials → Install a certificate → CA certificate.
You should see:
https://<your-domain>open on that device with no certificate warning.If not: on an iPhone, the switch in Certificate Trust Settings is still off. Firefox keeps its own list: Settings → Privacy & Security → View Certificates → Authorities → Import.
-
On one of those devices, open
https://<your-domain>/register, fill in your name, a username, a password and the Setup code from step 10, and choose Create account. This first account is the lab's admin.You should see: you are signed in, and the lab's set-up questions open.
If not:
That setup code is not right.: copy it again from step 10, all three groups and the dashes. -
Turn on alerts, the watchdog and weekly updates.
sudo host/install.sh
You should see:
Installed. Alerts go to ntfy topic: biomanager-…and two timers,biomanager-watchdog.timerandbiomanager-maintenance.timer. Subscribe to that topic in the ntfy app on your phone.If not:
command not found: you're not in the deploy folder. Runcd /opt/biomanager/Biomanager/deployfirst.
Done when: on another computer on the lab network,
https://<your-domain>/healthz shows ok with no certificate warning, and you can sign
in at https://<your-domain> as the admin.
BACKUP_DIR on a second disk and turn on off-site copies (After it's running).C · A university or department server
You need
- A Linux VM from IT, with an account on it that can use
sudo(step 1 asks for both). - A certificate from IT for its name: a certificate file and its key file.
- Your computer, on the campus network or VPN, with a terminal.
- Cost: often $0 a month; some IT departments charge.
- Time: IT's turnaround, then 30 minutes.
-
Send IT this request.
We'd like a small Linux VM (Ubuntu 24.04, 2 vCPU, 4 GB RAM, 40 GB disk) with Docker and its compose plugin, a DNS name such as biomanager.ourdept.example.edu, a TLS certificate for that name, and port 443 open to the campus network and VPN. It runs BioManager, a lab database, in Docker containers. Please give me an account on it that can use sudo.
You should see: a reply with the DNS name, how to sign in, and the certificate: a
.crtor.pemfile and its key.If not: IT can't issue a certificate: set
TLS=internalin step 6 instead offiles, skip step 5, and do route B's steps 11 and 12 after starting. -
Copy IT's two certificate files to the VM, from your computer.
scp <certificate-file> <key-file> <you>@<your-domain>:
<certificate-file>,<key-file>: the files from IT (in step 5, just their names).<you>: your account on the VM.<your-domain>: the VM's DNS name.You should see: both files copied, each at 100%.
If not:
Connection timed out: you're off campus. Connect the VPN. -
Sign in to the VM and check Docker.
ssh <you>@<your-domain>
docker compose version
You should see:
Docker Compose version v…If not:
permission denied while trying to connect to the Docker daemon socket: runsudo usermod -aG docker $USER, sign out and in again.docker: command not found: ask IT to install Docker. -
Download BioManager.
sudo mkdir -p /opt/biomanager && sudo chown "$USER" /opt/biomanager curl -fsSL -o /tmp/biomanager-server.tar.gz \ https://github.com/gaspolymerase/biomanager/releases/latest/download/biomanager-server.tar.gz tar -xzf /tmp/biomanager-server.tar.gz -C /opt/biomanager /opt/biomanager/Biomanager/deploy/host/load-image.sh
You should see:
Loaded image: ghcr.io/gaspolymerase/biomanager:<version>andLoaded. Start or update with: …If not:
Could not download: the VM can't reach github.com. Ask IT about a proxy, then run the last line again. -
Put the certificate where BioManager reads it.
cp ~/<certificate-file> /opt/biomanager/Biomanager/deploy/certs/server.crt cp ~/<key-file> /opt/biomanager/Biomanager/deploy/certs/server.key ls /opt/biomanager/Biomanager/deploy/certs
You should see:
server.crt server.keyIf not:
No such file: check the file names withls ~. -
Write the settings that need no choices.
cd /opt/biomanager/Biomanager/deploy cp .env.example .env && chmod 600 .env sed -i "s|^POSTGRES_PASSWORD=.*|POSTGRES_PASSWORD=$(openssl rand -hex 24)|" .env sed -i "s|^TLS=.*|TLS=files|; s|^BACKUP_DIR=.*|BACKUP_DIR=/opt/biomanager/backups|" .env
You should see: no output.
-
Enter your address and time zone: open the file, change the two lines, save with Ctrl+O, Enter, close with Ctrl+X.
nano .env
DOMAIN=<your-domain> TZ=<your-time-zone>
<your-domain>: the DNS name from IT, withouthttps://.<your-time-zone>: likeEurope/BerlinorAsia/Shanghai.You should see:
DOMAIN=near the top,TZ=about halfway down. -
Check the settings.
grep -E '^(DOMAIN|TLS|TZ|BACKUP_DIR)=' .env docker compose config --quiet && echo "settings ok"
You should see: your four lines, with
TLS=files, thensettings ok.If not:
set POSTGRES_PASSWORD in .env: run step 6 again.DOMAIN=biomanager.example.edu: the edit wasn't saved; repeat step 7. -
Start BioManager.
docker compose up -d --build
You should see:
biomanager-db-1,biomanager-app-1,biomanager-caddy-1andbiomanager-backup-1, eachStartedorHealthy.If not:
pull access denied: runhost/load-image.sh, then this again. -
Check that everything runs.
docker compose ps
You should see:
dbandapp(healthy),caddyUp,backup(healthy)or, for a few minutes,(health: starting).If not:
caddyrestarting:docker compose logs caddy; usually the key doesn't match the certificate, or the files are swapped. -
Get the setup code for the first account.
docker compose logs app | grep "setup code"
You should see:
No accounts yet. Create the first admin at /register with setup code 1a2b-3c4d-5e6f …If not: nothing: wait a minute and repeat.
-
On your computer, open
https://<your-domain>/register, fill in your name, a username, a password and the Setup code, and choose Create account. This first account is the lab's admin.You should see: you are signed in, and the lab's set-up questions open.
If not: a certificate warning on some devices: ask IT for the certificate with its full chain, put it in
server.crtagain and rundocker compose restart caddy. -
Turn on alerts, the watchdog and weekly updates.
sudo host/install.sh
You should see:
Installed. Alerts go to ntfy topic: biomanager-…. Subscribe to it in the ntfy app.If not:
command not found:cd /opt/biomanager/Biomanager/deployfirst.
Done when: from a computer on the campus network or VPN,
https://<your-domain>/healthz shows ok with no certificate warning, and you can sign
in as the admin.
D · A cloud VM with Tailscale recommended
The server has no open ports on the internet. Lab members open it at
https://biomanager.tail1234.ts.net (your own tailnet name) from any network, with the Tailscale app on.
You need
- An Oracle Cloud account. It asks for a card to verify you; Always Free resources are never charged. Pick your home region carefully: it can't be changed. (Or any provider's Ubuntu 24.04 VM with a cloud-init box: Hetzner about €4, DigitalOcean or AWS Lightsail about $5–7 a month.)
- A Tailscale account (free for up to 6 users; share the server with anyone else's own free account).
- Your computer, with a terminal and the Tailscale app.
- Cost: $0 a month on Oracle Always Free.
- Time: about an hour.
-
On your computer, make an SSH key. Press Enter at each question.
ssh-keygen -t ed25519
You should see:
Your public key has been saved in …/.ssh/id_ed25519.pubIf not:
… already exists. Overwrite (y/n)?: answer n and use the key you have. -
On your computer, download the server bundle and show its first-boot script.
curl -fsSL -o biomanager-server.tar.gz https://github.com/gaspolymerase/biomanager/releases/latest/download/biomanager-server.tar.gz tar -xzf biomanager-server.tar.gz cat Biomanager/deploy/cloud-init.yaml
You should see: a file that starts with
#cloud-config. You paste all of it in step 3.If not: Windows PowerShell says a parameter can't be found: type
curl.exeinstead ofcurl. -
Create the VM: Oracle Cloud console → ☰ → Compute → Instances → Create instance, with:
- Image: Change image → Ubuntu → Canonical Ubuntu 24.04.
- Shape: Change shape → Ampere → VM.Standard.A1.Flex, 2 OCPUs, 12 GB memory.
- Networking: a new virtual cloud network and public subnet; assign a public IPv4 address.
- Add SSH keys: Upload public key files (.pub) →
id_ed25519.pubfrom step 1. - Advanced options → Management → Initialization script → Paste cloud-init script: all of
cloud-init.yamlfrom step 2.
Then Create.
You should see: the instance Running within a few minutes, with a Public IP address on its page. Note it: it's
<public-ip>below.If not:
Out of capacity for shape VM.Standard.A1.Flex: pick another availability domain under Placement, or try again later. -
On your computer, sign in to the VM. Answer
yesto the fingerprint question.ssh ubuntu@<public-ip>
You should see: a prompt that starts
ubuntu@.If not:
Connection timed out: the VM is still booting; try again in two minutes.Permission denied (publickey):ssh -i ~/.ssh/id_ed25519 ubuntu@<public-ip>. -
Wait for the first-boot script to finish (5–10 minutes after the VM starts).
test -f /var/lib/biomanager-ready && echo ready
You should see:
readyIf not: nothing: it's still running.
sudo tail -f /var/log/cloud-init-output.logshows progress (Ctrl+C to stop watching). If that log never mentions Docker, the script wasn't pasted in step 3: terminate the VM and create it again. -
Put the VM on your Tailscale network.
sudo tailscale up --hostname=biomanager
You should see:
To authenticate, visit: https://login.tailscale.com/a/…. Open that link on your computer and sign in; the terminal then saysSuccess.If not:
tailscale: command not found: step 5 isn't finished. -
In the Tailscale admin console: Machines → biomanager → ⋯ → Disable key expiry.
You should see: Expiry disabled on the biomanager row.
If not: it's called
biomanager-1: an older machine has the name. Remove the old one (⋯ → Remove) and rename this onebiomanager(⋯ → Edit machine name). -
In the admin console, DNS: enable MagicDNS, then under HTTPS Certificates choose Enable HTTPS. Note the Tailnet name on that page, like
tail1234.ts.net.You should see: both on. Your server's address is
biomanager.plus your tailnet name: that is<your-domain>below.If not: no HTTPS option: turn on MagicDNS first.
-
On your computer, open the Tailscale app and sign in with the same account. Type
exitin the VM's window, then sign in again through Tailscale.ssh ubuntu@biomanager
You should see: the
ubuntu@prompt again. Use this connection from now on.If not:
Could not resolve hostname biomanager: Tailscale is off on your computer, signed in to another account, or MagicDNS is off (step 8). -
Download BioManager.
curl -fsSL -o /tmp/biomanager-server.tar.gz \ https://github.com/gaspolymerase/biomanager/releases/latest/download/biomanager-server.tar.gz tar -xzf /tmp/biomanager-server.tar.gz -C /opt/biomanager /opt/biomanager/Biomanager/deploy/host/load-image.sh
You should see:
Downloading BioManager <version> for arm64…, thenLoaded image: ghcr.io/gaspolymerase/biomanager:<version>andLoaded. Start or update with: …If not:
permission denied while trying to connect to the Docker daemon socket:exit,ssh ubuntu@biomanageragain, and repeat.Cannot mkdir: Permission denied:sudo chown ubuntu /opt/biomanager, and repeat. -
Write the settings that need no choices: a database password, Tailscale certificates and the backup folder.
cd /opt/biomanager/Biomanager/deploy cp .env.example .env && chmod 600 .env sed -i "s|^POSTGRES_PASSWORD=.*|POSTGRES_PASSWORD=$(openssl rand -hex 24)|" .env sed -i "s|^TLS=.*|TLS=tailscale|; s|^#COMPOSE_FILE=|COMPOSE_FILE=|; s|^BACKUP_DIR=.*|BACKUP_DIR=/opt/biomanager/backups|" .env
You should see: no output.
-
Enter your address and time zone: open the file, change the two lines, save with Ctrl+O, Enter, close with Ctrl+X.
nano .env
DOMAIN=<your-domain> TZ=<your-time-zone>
<your-domain>:biomanager.and your tailnet name from step 8, likebiomanager.tail1234.ts.net.<your-time-zone>: likeEurope/BerlinorAsia/Shanghai.You should see:
DOMAIN=near the top,TZ=about halfway down. -
Check the settings.
grep -E '^(DOMAIN|TLS|COMPOSE_FILE|TZ|BACKUP_DIR)=' .env docker compose config --quiet && echo "settings ok"
You should see:
DOMAIN=biomanager.tail1234.ts.net(with your tailnet),TLS=tailscale,COMPOSE_FILE=compose.yaml:compose.tailscale.yaml, yourTZ,BACKUP_DIR=/opt/biomanager/backups, thensettings ok.If not:
set POSTGRES_PASSWORD in .envor noCOMPOSE_FILEline: run step 11 again.DOMAIN=biomanager.example.edu: the edit wasn't saved; repeat step 12. -
Start BioManager.
docker compose up -d --build
You should see: after a minute or two,
biomanager-db-1,biomanager-app-1,biomanager-caddy-1andbiomanager-backup-1, eachStartedorHealthy.If not:
pull access denied for ghcr.io/gaspolymerase/biomanager: runhost/load-image.sh, then this again.container biomanager-app-1 is unhealthy:docker compose logs --tail 100 appsays why. -
Check that everything runs.
docker compose ps
You should see:
dbandapp(healthy),caddyUp, andbackup(healthy), or(health: starting)for a few minutes while it takes its first backup.If not: a service missing or
Restarting:docker compose logs --tail 100 <service>. -
Get the setup code for the first account.
docker compose logs app | grep "setup code"
You should see:
No accounts yet. Create the first admin at /register with setup code 1a2b-3c4d-5e6f (also saved in /data/setup-code).If not: nothing: the app is still starting. Wait a minute and repeat.
-
On your computer, with Tailscale on, open
https://<your-domain>/register, fill in your name, a username, a password and the Setup code, and choose Create account. This first account is the lab's admin.You should see: you are signed in, and the lab's set-up questions open.
If not: no answer or a certificate error: HTTPS isn't on in Tailscale (step 8) or the
COMPOSE_FILEline is missing (step 11). Fix it, rundocker compose up -d, anddocker compose logs caddyif it still fails. -
Turn on alerts, the watchdog and weekly updates.
sudo host/install.sh
You should see:
Installed. Alerts go to ntfy topic: biomanager-…and two timers,biomanager-watchdog.timerandbiomanager-maintenance.timer. Subscribe to that topic in the ntfy app on your phone.If not:
command not found:cd /opt/biomanager/Biomanager/deployfirst. -
Close SSH to the internet: Oracle Cloud console → the instance → Subnet (under Primary VNIC) → Security Lists → Default Security List → Ingress Rules, tick the rule with destination port 22 → Remove. Then, on your computer:
ssh -o ConnectTimeout=10 ubuntu@<public-ip>
You should see:
Connection timed out, whilessh ubuntu@biomanagerstill works.If not: it still connects: another rule opens port 22 (look for a network security group on the instance) and remove it too.
-
Optional, recommended: keep Oracle from stopping the VM. Oracle Cloud console → Billing → Upgrade and Manage Payment → Upgrade to Pay As You Go. Always Free resources stay free.
You should see: the account shown as Pay As You Go.
If you skip this: Oracle stops an Always Free VM that looks idle for a week. Start it again in Compute → Instances; nothing is lost.
Done when: on your phone or computer with Tailscale on,
https://<your-domain>/healthz shows ok, you can sign in at
https://<your-domain> as the admin, and ssh ubuntu@<public-ip> times out.
E · A cloud VM with your own domain
No app needed: anyone opens https://biomanager.yourlab.example. The sign-in page is on the open
internet, so use strong passwords, and consider sign-in with Google or Microsoft.
You need
- An Oracle Cloud account (free; a card verifies you; the home region can't be changed), or any provider's Ubuntu 24.04 VM with a cloud-init box.
- A domain (about $10–15 a year) at a registrar where you can add DNS records, such as Cloudflare, Porkbun or Namecheap; or a subdomain from your department.
- An email address for Let's Encrypt, which issues the certificate.
- Your computer, with a terminal.
- Cost: about $1 a month (the domain) on Oracle Always Free.
- Time: 1–2 hours; a new DNS record can take up to an hour to work everywhere.
-
On your computer, make an SSH key. Press Enter at each question.
ssh-keygen -t ed25519
You should see:
Your public key has been saved in …/.ssh/id_ed25519.pubIf not:
… already exists. Overwrite (y/n)?: answer n and use the key you have. -
On your computer, download the server bundle and show its first-boot script.
curl -fsSL -o biomanager-server.tar.gz https://github.com/gaspolymerase/biomanager/releases/latest/download/biomanager-server.tar.gz tar -xzf biomanager-server.tar.gz cat Biomanager/deploy/cloud-init.yaml
You should see: a file that starts with
#cloud-config. You paste all of it in step 3.If not: Windows PowerShell says a parameter can't be found: type
curl.exeinstead ofcurl. -
Create the VM: Oracle Cloud console → ☰ → Compute → Instances → Create instance, with:
- Image: Change image → Ubuntu → Canonical Ubuntu 24.04.
- Shape: Change shape → Ampere → VM.Standard.A1.Flex, 2 OCPUs, 12 GB memory.
- Networking: a new virtual cloud network and public subnet; assign a public IPv4 address.
- Add SSH keys: Upload public key files (.pub) →
id_ed25519.pubfrom step 1. - Advanced options → Management → Initialization script → Paste cloud-init script: all of
cloud-init.yamlfrom step 2.
Then Create.
You should see: the instance Running, with a Public IP address on its page:
<public-ip>below.If not:
Out of capacity for shape VM.Standard.A1.Flex: pick another availability domain under Placement, or try again later. -
Open ports 80 and 443: the instance → Subnet (under Primary VNIC) → Security Lists → Default Security List → Add Ingress Rules: source CIDR
0.0.0.0/0, IP protocol TCP, destination port80; + Another Ingress Rule, the same with443; Add Ingress Rules.You should see: two new rows, TCP 80 and TCP 443. Let's Encrypt needs port 80 to issue the certificate.
-
At your registrar, add a DNS A record: name
biomanager, value<public-ip>. Then, on your computer:nslookup <your-domain>
<your-domain>:biomanager.and your domain, likebiomanager.yourlab.example.You should see:
Address: <public-ip>under the name.If not: no address yet: wait 10 minutes and repeat. On Cloudflare, set the record to DNS only (grey cloud), not proxied.
-
Sign in to the VM. Answer
yesto the fingerprint question.ssh ubuntu@<public-ip>
You should see: a prompt that starts
ubuntu@.If not:
Connection timed out: try again in two minutes.Permission denied (publickey):ssh -i ~/.ssh/id_ed25519 ubuntu@<public-ip>. -
Wait for the first-boot script to finish (5–10 minutes after the VM starts).
test -f /var/lib/biomanager-ready && echo ready
You should see:
ready. Then typeexitand sign in again (step 6), so your account can use Docker.If not: nothing:
sudo tail -f /var/log/cloud-init-output.logshows progress. If that log never mentions Docker, the script wasn't pasted in step 3: terminate the VM and create it again. -
Download BioManager.
curl -fsSL -o /tmp/biomanager-server.tar.gz \ https://github.com/gaspolymerase/biomanager/releases/latest/download/biomanager-server.tar.gz tar -xzf /tmp/biomanager-server.tar.gz -C /opt/biomanager /opt/biomanager/Biomanager/deploy/host/load-image.sh
You should see:
Loaded image: ghcr.io/gaspolymerase/biomanager:<version>andLoaded. Start or update with: …If not:
permission denied while trying to connect to the Docker daemon socket:exit, sign in again, and repeat. -
Write the settings that need no choices.
cd /opt/biomanager/Biomanager/deploy cp .env.example .env && chmod 600 .env sed -i "s|^POSTGRES_PASSWORD=.*|POSTGRES_PASSWORD=$(openssl rand -hex 24)|" .env sed -i "s|^TLS=.*|TLS=acme|; s|^BACKUP_DIR=.*|BACKUP_DIR=/opt/biomanager/backups|" .env
You should see: no output.
-
Enter your address, email and time zone: open the file, change the three lines, save with Ctrl+O, Enter, close with Ctrl+X.
nano .env
DOMAIN=<your-domain> ACME_EMAIL=<your-email> TZ=<your-time-zone>
<your-domain>: the name from step 5.<your-email>: Let's Encrypt writes there before a certificate expires.<your-time-zone>: likeEurope/BerlinorAsia/Shanghai.You should see:
DOMAIN=andACME_EMAIL=near the top,TZ=about halfway down. -
Check the settings.
grep -E '^(DOMAIN|TLS|ACME_EMAIL|TZ|BACKUP_DIR)=' .env docker compose config --quiet && echo "settings ok"
You should see: your five lines, with
TLS=acme, thensettings ok.If not:
set POSTGRES_PASSWORD in .env: run step 9 again.DOMAIN=biomanager.example.edu: the edit wasn't saved; repeat step 10. -
Start BioManager.
docker compose up -d --build
You should see:
biomanager-db-1,biomanager-app-1,biomanager-caddy-1andbiomanager-backup-1, eachStartedorHealthy.If not:
pull access denied: runhost/load-image.sh, then this again. -
Check that Caddy got the certificate.
docker compose logs caddy | grep "certificate obtained"
You should see: a line with
certificate obtained successfullyand your domain.If not: nothing yet: wait a minute and repeat. Lines with
challenge failedortimeout: the DNS record (step 5) or port 80 (step 4) isn't right yet. Fix it, thendocker compose restart caddy. -
Get the setup code for the first account.
docker compose logs app | grep "setup code"
You should see:
No accounts yet. Create the first admin at /register with setup code 1a2b-3c4d-5e6f …If not: nothing: wait a minute and repeat.
-
Open
https://<your-domain>/register, fill in your name, a username, a password and the Setup code, and choose Create account. This first account is the lab's admin.You should see: you are signed in, and the lab's set-up questions open.
If not:
That setup code is not right.: copy it again, all three groups and the dashes. -
Turn on alerts, the watchdog and weekly updates.
sudo host/install.sh
You should see:
Installed. Alerts go to ntfy topic: biomanager-…. Subscribe to it in the ntfy app.If not:
command not found:cd /opt/biomanager/Biomanager/deployfirst.
Done when: on a phone on mobile data, https://<your-domain>/healthz shows
ok with a padlock, and you can sign in at https://<your-domain> as the admin.
Bring the desktop app's records
Records, history and IDs all come along. Do this on a new server, before its first start: in route B, C, D or E, after Check the settings, do these steps instead of the rest of the route up to Turn on alerts. You then sign in with your existing account: no setup code.
-
Quit the desktop app. Then, on that computer, copy its database and uploaded files to the server.
scp "$HOME/Library/Application Support/Biomanager/data/biomanager.db" <you>@<server>:/tmp/lab.db scp -r "$HOME/Library/Application Support/Biomanager/uploads" <you>@<server>:/tmp/lab-uploads
That is a Mac. On Windows the folder is
$env:APPDATA\Biomanager(PowerShell), on Linux~/.local/share/Biomanager.<you>@<server>: how you sign in to the server, likeubuntu@biomanager.You should see: each file copied at 100%.
If not:
uploads: No such file or directory: the app has no uploads. Skip the second line, and the second line of step 4. -
On the server, test the copy. It changes nothing.
cd /opt/biomanager/Biomanager/deploy docker compose up -d db docker compose run --rm --no-deps -v /tmp/lab.db:/import/lab.db:ro app \ sh -c 'python scripts/migrate-to-postgres.py --dry-run /import/lab.db "$DATABASE_URL"'
You should see:
copied : … rows in … tables, row counts verifiedanddry run : rolled back, nothing kept.If not: a list of values PostgreSQL would refuse: fix those records in the desktop app, then repeat step 1.
-
Copy it for real.
docker compose run --rm --no-deps -v /tmp/lab.db:/import/lab.db:ro app \ sh -c 'python scripts/migrate-to-postgres.py /import/lab.db "$DATABASE_URL"'
You should see:
copied : … row counts verified, with nodry runline.If not:
The copy failed and was rolled back: the server's database isn't empty (BioManager was started before). Ask on GitHub. -
Start BioManager and copy the uploaded files in.
docker compose up -d --build docker compose cp /tmp/lab-uploads/. app:/data/uploads/
You should see: the four services
Started, thenSuccessfully copied.
Done when: you sign in at https://<your-domain> with your desktop account
and see your records. Then do your route's Turn on alerts step.
The same steps rebuild a lost server from a lab computer's copy: use the newest .db in its
lab-copies/…/db folder and its uploads folder.
Other routes
- Cloudflare Tunnel
- An ordinary address like E, with no open port:
cloudflaredon the server connects out to Cloudflare, and Cloudflare Access can ask for a lab email login first. Not packaged; the AI guide has notes for it. - Without Docker
- A Python web app (gunicorn) on PostgreSQL behind any HTTPS proxy: deploy/README.md, Without Docker. With Docker, backups, updates and restores are one command each.
Part three
Once it's running
After it's running
Each item links to its checklist in the runbook, which is also in the bundle as
deploy/RUNBOOK.md. Security updates install nightly, and the containers refresh on Sundays.
- Set up the lab: the admin's first sign-in asks what the lab keeps (user guide).
- Write down where everything is, and keep it off the server: Where everything is.
- Turn on off-site backups (Backblaze B2, free at this size):
sudo /opt/biomanager/Biomanager/deploy/host/offsite-setup.sh, after making the bucket. - An alert arrived: what each one means.
- Someone joins: share the server with them (Tailscale), approve them in Settings → Manage users. Phones: the Android app, or Safari → Share → Add to Home Screen on iPhone. Someone joins.
- Someone leaves: Someone leaves.
- Update to a new version: Updating the app (and if it goes wrong).
- Put a backup back: Restore a backup.
- The site is down: The site is down.
- The server is lost, or you move to another: The server is lost, Moving to another server.
- An admin is locked out: An admin is locked out.
- Let a guest in from the internet for a few days, with no Tailscale (route D): a code from
Guests, then
sudo host/internet-access.sh on; they openhttps://<your-domain>:8443/guest. Letting a guest in, user guide. - Sign in with Google, Microsoft or your institution: register the server with the provider,
put its client ID and secret in
.env(BIOMANAGER_GOOGLE_*,BIOMANAGER_MICROSOFT_*,BIOMANAGER_OIDC_*for OpenID Connect,BIOMANAGER_CILOGON_*for a SAML-only university), thendocker compose up -d. Signing in with Google or Microsoft.
Keeping the data safe
Several independent copies, so no single failure (a deleted VM, a dead disk, a stolen laptop, a bad update) loses the lab's records.
| 1 · Every night | The server backs up the database and uploaded files, checks each backup can be read, and keeps the last 30. Automatic on every server. |
|---|---|
| 2 · Every week | The newest backup is restored into a scratch database and checked. Automatic. |
| 3 · Off-site | Encrypted copies in cloud storage, kept 30 days, 12 weeks and 24 months; with the
bucket's Object Lock on, safe even from someone who takes over the server. Backblaze B2's first 10 GB are free.
sudo /opt/biomanager/Biomanager/deploy/host/offsite-setup.sh. |
| 4 · On lab computers | The desktop app keeps its own copy of the whole lab: on the server,
Settings → Copies of the lab on your computers → Make a key; in the desktop app, Settings → Keep a copy of
your lab server, with the address and the key. It takes a fresh copy every day while open and keeps the last 14.
An admin's Mac can also pull the server's nightly backups: deploy/mac/install.sh
(how). |
| 5 · Everyone | Export on every sheet gives a CSV; Settings → Export my data downloads your own records and notebook pages. |
| 6 · Undo and history | Every bulk change can be undone from Batches; the Audit log shows every edit, who made it and what it was before. |
Restoring never deletes what it replaces: Restore a backup.
Questions
- Is Oracle's free VM really free?
- Always Free resources carry no charge; the card is for identity. Oracle may stop a free-tier VM that looks idle for a week: start it again and nothing is lost, or upgrade to Pay As You Go (route D, step 20) to stop it happening.
- Is Tailscale safe for lab data?
- Tailscale connects devices directly with WireGuard encryption and can't read the traffic. Anyone outside your tailnet can't see the server at all.
- How big does the server need to be?
- 2 CPU cores, 2 GB of memory and 20 GB of disk. A lab with tens of thousands of animals uses well under 1 GB of database.
- Can several labs share one server?
- Run one BioManager per lab (each its own folder and domain), or one for a whole facility, where each lab keeps its own databases.
- A step didn't work. Who can help?
- Open an issue with your route, the step number and what it printed.