Production deployment
Both services build from the repo root (monorepo). The frontend container runs
nginx, which serves the built SPA at / and reverse-proxies /api to the
backend container. Only the frontend port needs to be published — the backend
is reached internally over the compose network as backend:8000.
host.com/ -> frontend (nginx static SPA)
host.com/api/... -> backend (FastAPI, /api prefix stripped)
Build
echo $VITE_API_TARGET=https://radiusadmin.example.com > .build/prod/.env
docker compose -f .build/prod/compose.yml up -d --build
Running from published images
- compose.yml
services:
database:
image: mysql
hostname: database
environment:
- MYSQL_RANDOM_ROOT_PASSWORD=yes
- MYSQL_USER=radius
- MYSQL_PASSWORD=radius
- MYSQL_DATABASE=radius
volumes:
- ./mysql:/var/lib/mysql
freeradius:
image: freeradius/freeradius-server
hostname: freeradius
ports:
- 1812:1812/udp
- 1813:1813/udp
# volumes:
# - ./freeradius/sql:/etc/freeradius/mods-enabled/sql
# - /etc/freeradius/3.0/:/etc/freeradius/
depends_on:
- database
adminer:
image: dockette/adminer:mysql
hostname: adminer
ports:
- 8001:80
depends_on:
- database
backend:
image: git.shihaam.dev/sarlink/radadmin/backend
hostname: backend
env_file:
- .env
depends_on:
- database
frontend:
image: git.shihaam.dev/sarlink/radadmin/frontend
hostname: frontend
ports:
- 8000:80
depends_on:
- backend
- Create
compose.ymlwith the above yaml - Create .env and fill
# --- Database (FreeRADIUS) ---
DB_HOST=database
DB_PORT=3306
DB_USER=radadmin
DB_PASSWORD=changeme
DB_NAME=radius
# --- API ---
API_KEY=changeme
- Start the services
docker compose up -dand wait few mins for db to initilize - copy db schema from freeradius and backend to mysql and import it
docker compose cp freeradius:/etc/freeradius/mods-config/sql/main/mysql/schema.sql .
docker compose cp schema.sql database:/schema.sql
docker compose exec database sh -c 'mysql -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DATABASE" < /schema.sql'
docker compose exec backend python migrate.py
rm radadmin_schema.sql schema.sql