Getting Started

Tom Labs can run in two modes: on an Actual VPS (TomCloudLab) or as a local Docker VPS (local_dev_lab).

TL;DR — install in one line Ubuntu / Debian · macOS
$ curl -fsSL https://cloud.tomweb.in/install.sh | sudo bash

Installs Docker + Traefik + WireGuard + Code Server + PostgreSQL. Automatically detects your OS and provisions a complete secure lab environment in seconds.

Manual Server Infrastructure

Manual VPS provisioning
Manual SSH key configuration
Nginx reverse proxy setup
Certbot SSL generation
Database user/password config
Exposed public ports
Hours of setup. Many failure points.
vs

Tom Labs Orchestration Layer

Docker Compose orchestrated
WireGuard VPN (Middleware)
Traefik edge routing (Middleware)
Automatic Let's Encrypt SSL
Dynamic routing to lab containers (e.g. Apache)
1 single script to manage everything.

No manual configs. No port forwarding. No hassle.

Choose Your Migration Path

Tom Labs supports two deployment models:
Option 1: For a public server with a static IP.
Option 2: For local development or behind a firewall using Cloudflare Zero Trust.

Option 1: Bare-Metal Server (VPS)

Run interactively on a fresh Ubuntu 24.04 server:

curl -fsSL https://cloud.tomweb.in/install.sh | sudo bash
  • Select [1] VPS Bare-Metal Server Setup
  • Enter your public domains when prompted
  • The script installs everything natively!
Option 2: Docker + Cloudflare Tunnel

Run locally on your Mac/Linux/Windows machine:

curl -fsSL https://cloud.tomweb.in/install.sh | sudo bash
  • Select [2] Docker Container Local Setup
  • The script generates your configs and starts the orchestration container!

Step 2: Required Configuration & Build

Before you can use Tom Labs, you must configure your environment and build the lab images. Follow the instructions for your chosen setup option:

ℹ️ Option 1 Users: Configure Environment

# 1. Edit configuration files with your API keys
nano /var/www/env.json
nano /var/www/labs/session.json

# 2. Build the Essentials Lab natively on the host
labsctl build essentials:lab

⚠️ Option 2 Users: Configure & Enter Container

# 1. Navigate to the default installation directory
cd ~/tom-cloud-labs

# 2. Edit configuration files with your API keys
nano env.json
nano session.json

# 3. Add your Cloudflare TUNNEL_TOKEN
nano docker-compose.yml

# 4. Apply your changes
docker compose down && docker compose up -d

# 5. Enter the orchestration container to build labs
docker exec -it TomCloudLab bash
labsctl build essentials:lab

Architecture Deep Dive: The Installation Flow

How install.sh securely fetches the repository and instantly hands off to Migrate.sh for an interactive setup experience.

graph TD A["curl install.sh | sudo bash"] --> B["install.sh
Downloads the latest repo from GitHub"] B --> C["Migrate.sh
Instantly takes over & interactively prompts you"] C --> D["Option 1: VPS
Configures bare-metal natively"] C --> E["Option 2: Docker
Generates container orchestration"] D --> F["Runs directly on host"] E --> G["Runs inside container"] classDef default fill:#f9f9f9,stroke:#e5e7eb,stroke-width:1px,color:#111827,rx:8px,ry:8px,padding:16px; classDef dark fill:#1c1917,stroke:#44403c,stroke-width:2px,color:#f8fafc,rx:8px,ry:8px; classDef option1 fill:#ecfdf5,stroke:#a7f3d0,stroke-width:2px,color:#065f46; classDef option2 fill:#fff1f2,stroke:#fecdd3,stroke-width:2px,color:#9f1239; class B dark; class D option1; class E option2;

The Two Layers

install.sh Migrate.sh
Size ~150 lines ~1800 lines
Job Check root/OS, fetch a pinned copy of the repo, hand off Everything else — the actual provisioning
Changes how often Rarely Whenever a feature is added
Lives where Hosted at the curl URL Inside the repo, fetched fresh each run

install.sh never installs Apache, MySQL, MongoDB, Docker, etc. itself. It only ensures git, curl, openssl exist, clones a pinned version of the repo, then execs Migrate.sh — at which point install.sh is gone and you're inside the real installer.

Option 1 (VPS) vs Option 2 (Docker)

This separation already exists in Migrate.sh. The Docker-only block is gated by a single condition. Everything inside it — generating Dockerfile, docker-compose.yml, entrypoint.sh, init-services.sh, config.json, then running docker compose up -d --build — only runs when that condition is true, and the block exits when done.

The VPS section never references any of those four files. It installs Apache, PHP, MySQL, MongoDB, PostgreSQL, Redis, RabbitMQ, WireGuard, and Traefik directly on whatever machine you ran it on, via apt-get and systemd.

Option 1 — VPS Option 2 — Docker
Selected by --mode=vps (or menu choice 1) --mode=docker (or menu choice 2)
docker-compose.yml Never generated Generated, then run via docker compose up
entrypoint.sh Never generated Generated, baked into the image
Core Services Installed straight onto this machine Installed only inside the container — host stays untouched
End result runs on The machine you ran it on A container managed by docker compose

Re-run Safety & Practical Guidance

  • It's safe to rerun install.sh as many times as needed after a failure — same command, same flags. WireGuard keys and DB users are generated defensively (e.g., CREATE USER IF NOT EXISTS).
  • Want a permanently fixed password? Pass DB_PASS=... and MQ_PASS=... explicitly instead of letting it auto-generate.
  • Check /var/log/tom-cloud-labs-install.log (from install.sh) and /tmp/migrate_cmd.log (printed automatically by Migrate.sh on failure) before retrying — most failures are transient network blips during apt/git, and a straight retry resolves them.
  • install.sh reuses credentials saved in /root/tom-cloud-labs-credentials.txt from a previous run unless explicitly overridden, preventing quietly rotating passwords on partial failures.

Verify Your Database (MongoDB Compass)

Tom Labs bundles MongoDB 8.0 securely. You can verify your connection and inspect user/lab records instantly using MongoDB Compass.

Connection String
# For local setups, connect using this URI:
mongodb://admin:Tombootroot@127.0.0.1:27017/tom_labs_db?authSource=admin

# 1. Open MongoDB Compass
# 2. Paste the URI above
# 3. View your 'users' and 'deployed_labs' collections!