Skip to content

First-Time Developer Setup Guide

Target Audience: New developers joining the Uplink project
Time Required: ~30 minutes
Last Updated: March 6, 2026


Prerequisites

Required Software

  1. Docker Desktop (Mac/Windows) or Docker Engine (Linux)
  2. Docker Desktop Download
  3. Includes Docker Compose
  4. Verify installation:

    docker --version  # Should be 20.10+
    docker compose version  # Should be v2.0+
    

  5. Git

    git --version  # Should be 2.x+
    

  6. Code Editor (VS Code recommended)

Linux-Specific Setup

# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# Add your user to docker group (IMPORTANT!)
sudo usermod -aG docker $USER

# Log out and back in for group membership to take effect
# Then verify:
docker run hello-world  # Should run without sudo

Step 1: Clone Repository

# Clone using SSH (recommended)
git clone git@github.com:SensationalSystems/uplink.git
cd uplink

# Or using HTTPS
git clone https://github.com/SensationalSystems/uplink.git
cd uplink

Step 2: Configure Environment Variables

⚠️ IMPORTANT: Do NOT Copy .env from Git

The .env file is gitignored and contains secrets. Never commit it to git.

Create Your Own .env File

# Copy the template
cp .env.example .env

# Edit with your preferred editor
nano .env   # or code .env, vim .env, etc.

What You MUST Change

Open .env and update these values:

1. Generate a Unique SECRET_KEY

Each developer needs their own SECRET_KEY to avoid conflicts:

# Generate a new one:
python3 -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())'

# Paste the output into .env:
SECRET_KEY=your-generated-key-here-abc123xyz

2. Get Shared Credentials from Team

Ask your team lead for these shared credentials:

  • Production Database (for ./sync-prod-db.sh)

    PROD_DATABASE_HOST=sensational-cluster-xxx.db.ondigitalocean.com
    PROD_DATABASE_PORT=25060
    PROD_DATABASE_NAME=uplink
    PROD_DATABASE_USER=uplink
    PROD_DATABASE_PASS=ask-team-lead
    

  • PrestaShop API Keys (both UK and EU):

    PRESTASHOP_API_KEY=ask-team-lead
    EU_PRESTASHOP_API_KEY=ask-team-lead
    

  • Shipping APIs (FedEx, Royal Mail):

    FEDEX_PROD_CLIENT_ID=ask-team-lead
    FEDEX_PROD_CLIENT_SECRET=ask-team-lead
    ROYALMAIL_OBA_API_KEY=ask-team-lead
    

  • DigitalOcean Spaces (file storage):

    SPACES_ACCESS_KEY_ID=ask-team-lead
    SPACES_SECRET_ACCESS_KEY=ask-team-lead
    

  • Other APIs (Mailgun, Xero):

    MAILGUN_API_KEY=ask-team-lead
    XERO_CLIENT_ID=ask-team-lead
    

3. Keep As-Is (Docker Defaults)

These settings are fine for all developers using Docker:

# Local Docker MySQL credentials (not sensitive - it's local only)
DB_NAME=uplink
DB_USER=uplink
DB_PASSWORD=admin
DB_ROOT_PASSWORD=rootadmin

# Django will connect to Docker containers
DATABASE_HOST=db        # Docker service name
DATABASE_PORT=3306
DATABASE_NAME=uplink
DATABASE_USER=uplink
DATABASE_PASS=admin

REDIS_HOST=redis        # Docker service name

Why these are safe to share: - They only apply to local Docker containers - Not accessible outside your machine - No security risk if everyone uses the same values


Step 3: Start Docker Environment

Build Images

# Build all Docker images (takes 3-5 minutes first time)
docker compose -f docker-compose.yml -f docker-compose.dev.yml build

Start All Services

# Start in detached mode (runs in background)
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d

# Or use the deploy script (auto-detects development mode)
./deploy.sh docker-up

Verify Services are Running

docker compose ps

# You should see:
# - uplink_web      (running)
# - uplink_daphne   (running)
# - uplink_huey     (running)
# - uplink_redis    (running)
# - uplink_db       (running)  ← MySQL container!

If any service shows "exited" or "unhealthy":

# Check logs for that service
docker compose logs web
docker compose logs db


Step 4: Initialize Database

Run Migrations

# Apply all database schema migrations
docker compose exec web python manage.py migrate

Expected output:

Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  [... many more ...]
  Applying sessions.0001_initial... OK

Create Superuser

# Create your admin account
docker compose exec web python manage.py createsuperuser

# Follow prompts:
# - Username: your-name
# - Email: you@sensational.systems
# - Password: (choose a secure password)

Test Database Connection

# Quick connection test
docker compose exec web python -c "import django; django.setup(); from django.db import connection; connection.ensure_connection(); print('✓ Database connected!')"

To get real data for development:

Run the Sync Script

./sync-prod-db.sh

The script will: 1. Download production database from DigitalOcean 2. Ask if you want to sanitize sensitive data (say yes) 3. Confirm before replacing your local database 4. Import the data 5. Run migrations to ensure compatibility

When asked "Sanitize sensitive data?" → Type y - This anonymizes user emails, passwords, API tokens - Makes it safe for local development

When asked "Continue?" → Type y - This confirms you want to replace your empty local database

Troubleshooting Sync Issues

"Production database credentials not configured" - Go back to Step 2 and add PROD_DATABASE_* credentials to .env

"Access denied" - Check with team lead that your IP is whitelisted in DigitalOcean - Verify password in .env is correct

"mysqldump: unknown option '--set-gtid-purged'" - Your MySQL client tools are outdated - The script will automatically handle this now - Or upgrade: sudo apt install mysql-client (Linux)

See full troubleshooting: PRODUCTION_DB_SYNC.md


Step 6: Collect Static Files

# Collect CSS, JavaScript, images for Django admin
docker compose exec web python manage.py collectstatic --noinput --clear

Application URLs

  • Main Application: http://localhost:8001
  • Django Admin: http://localhost:8001/admin
  • WebSocket (Daphne): http://localhost:9000
  • Redis: localhost:6381 (not HTTP - for debugging only)
  • MySQL: localhost:3309 (for MySQL Workbench, DBeaver, etc.)

Log In

  • Go to http://localhost:8001/admin
  • Username: your-superuser-name
  • Password: your-password

Step 8: Monitor Logs (Essential for Development)

Watch Real-Time Logs

# All key services (recommended during development)
docker compose logs -f web daphne huey

# Just HTTP requests (like Django runserver)
docker compose logs -f web

# Last 50 lines, then follow
docker compose logs --tail=50 -f web daphne huey

Pro Tip: Keep a terminal open with logs running while you develop!


Key Differences from Traditional Django Setup

You DON'T Need:

  • Local MySQL installation - Docker provides it
  • Python virtual environment - Docker provides it
  • pip install or uv sync - Docker builds include dependencies
  • python manage.py runserver - Gunicorn runs in Docker

You DO:

  • Use docker compose exec web python manage.py [command] instead of python manage.py [command]
  • Edit code on your host machine - changes sync automatically via volume mount
  • Access services via localhost:8001 instead of localhost:8000
  • Check logs with docker compose logs instead of terminal output

Common Development Tasks

Running Django Management Commands

# General pattern:
docker compose exec web python manage.py [command]

# Examples:
docker compose exec web python manage.py makemigrations
docker compose exec web python manage.py migrate
docker compose exec web python manage.py shell
docker compose exec web python manage.py test

Accessing Container Shell

# Open bash inside web container
docker compose exec web bash

# Now you're inside the container
# Run commands directly:
python manage.py check
ls -la /app
env | grep DATABASE
exit  # when done

Restarting Services

# Restart specific service (after code changes)
docker compose restart web

# Restart all services
docker compose restart

# Stop all services
docker compose down

# Start again
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d

Viewing Database

Option 1: Django Shell

docker compose exec web python manage.py shell

# Inside shell:
from catalogue.models import Product
Product.objects.count()

Option 2: Database Client (DBeaver, MySQL Workbench) - Host: localhost - Port: 3309 (not 3306!) - Database: uplink - User: uplink - Password: admin


Understanding Docker Volumes

What is Mounted?

From docker-compose.dev.yml:

volumes:
  - .:/app  # Your entire project directory

This means: - ✅ Edit code in VS Code on your host machine - ✅ Changes immediately reflect in Docker container - ✅ No rebuild needed for Python code changes - ✅ Gunicorn auto-reloads on changes (via --reload flag)

MySQL Data Persistence

volumes:
  - mysql_data:/var/lib/mysql
  • MySQL data persists even if you stop containers
  • docker compose down → Data preserved ✅
  • docker compose down -v → Data DELETED ⚠️

Verifying Your Setup

Run this checklist to confirm everything works:

# 1. All containers running?
docker compose ps
# Should show 5 services as "running"

# 2. Database connection works?
docker compose exec web python -c "import django; django.setup(); from django.db import connection; connection.ensure_connection(); print('✓ DB OK')"

# 3. Redis connection works?
docker compose exec redis redis-cli ping
# Should return: PONG

# 4. Migrations applied?
docker compose exec web python manage.py showmigrations | grep "\[ \]"
# Should return nothing (all migrations have [X])

# 5. Can access web interface?
curl -I http://localhost:8001
# Should return: HTTP/1.1 200 OK or 302 Found

# 6. Can access admin?
curl -I http://localhost:8001/admin/
# Should return: HTTP/1.1 200 OK or 302 Found

If all checks pass: ✅ You're ready to develop!


Next Steps

  1. Read the full dev guide: LOCAL_DEVELOPMENT.md
  2. Learn the codebase:
  3. /catalogue/ - Product catalog
  4. /orders/ - Order management
  5. /stock/ - Inventory tracking
  6. /prestashop/ - PrestaShop integration
  7. Set up your IDE: Configure VS Code with Python extension
  8. Join the team: Ask questions in team chat!

Troubleshooting

"Port is already allocated"

# Check what's using port 8001
sudo lsof -i :8001

# Stop the conflicting process
sudo kill -9 <PID>

"Cannot connect to Docker daemon"

# On Linux: Did you add yourself to docker group?
sudo usermod -aG docker $USER
# Then log out and back in

# On Mac/Windows: Is Docker Desktop running?

"Database connection failed"

# Check .env has correct values
cat .env | grep DATABASE

# Verify db container is healthy
docker compose ps db

# Check db logs
docker compose logs db

"Module not found" errors

# Rebuild Docker image to install dependencies
docker compose build web
docker compose up -d web

Still Having Issues?

See full troubleshooting guide: LOCAL_DEVELOPMENT.md#troubleshooting


Security Reminders

  • ⚠️ Never commit .env to git (already in .gitignore)
  • ⚠️ Use unique SECRET_KEY per developer
  • ⚠️ Share credentials via secure channel (1Password, LastPass, etc.)
  • ⚠️ Production DB credentials are for READ ONLY (via sync script)
  • ⚠️ Docker MySQL is local only - not accessible outside your machine

Quick Reference Card

# Start dev environment
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d

# View logs (keep this running!)
docker compose logs -f web daphne huey

# Run Django commands
docker compose exec web python manage.py [command]

# Restart service after code changes
docker compose restart web

# Access container shell
docker compose exec web bash

# Stop everything
docker compose down

# Nuclear reset (deletes database!)
docker compose down -v

Welcome to the team! 🎉

If you have questions, check the docs or ask in team chat.