The Servala Self-Service Portal
  • Python 76.8%
  • HTML 15.5%
  • JavaScript 4.4%
  • CSS 1.7%
  • Shell 1.3%
  • Other 0.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-07-27 03:02:09 +00:00
.claude Consolidate billing migrations 2026-04-14 11:02:53 +02:00
.forgejo chore(deps): update https://github.com/renovatebot/github-action action to v46.1.21 2026-07-27 03:02:05 +00:00
deployment feat(deploy): add Talos deployment target alongside OpenShift 2026-07-07 14:37:18 +02:00
docker use system certs for caddy 2026-05-29 11:35:20 +02:00
docs support instances parameter in provisioning deep links 2026-07-17 12:27:31 +02:00
hack feat(dev): per-worktree dev server port and database helpers 2026-07-13 16:42:47 +02:00
src support instances parameter in provisioning deep links 2026-07-17 12:27:31 +02:00
.dockerignore dont include local sqlite file in docker build 2025-03-21 14:24:21 +01:00
.env.example document missing env vars 2026-07-07 14:03:12 +02:00
.gitignore gitignore local .envrc 2026-07-07 15:25:50 +02:00
.pre-commit-config.yaml add a pre-commit configuration 2025-03-07 09:21:48 +01:00
.python-version Update python Docker tag 2025-11-11 03:02:31 +00:00
CLAUDE.md feat(dev): per-worktree dev server port and database helpers 2026-07-13 16:42:47 +02:00
docker-compose.yml Add staging database copy tooling 2026-04-14 11:02:53 +02:00
Dockerfile ssh is not needed anymore 2026-05-29 11:35:46 +02:00
justfile feat(dev): per-worktree dev server port and database helpers 2026-07-13 16:42:47 +02:00
LICENSE Initial commit 2025-03-03 15:26:47 +00:00
pyproject.toml bump version 2026.07.07-0 -> 2026.07.15-0 2026-07-15 07:34:04 +02:00
README.md bump version 2026.07.07-0 -> 2026.07.15-0 2026-07-15 07:34:04 +02:00
renovate.json no patch updates for python 2026-01-29 13:17:09 +01:00
uv.lock Merge pull request 'chore(deps): update dependency coverage to >=7.15.1' (#609) from renovate/coverage-7.x into main 2026-07-15 05:29:36 +00:00

Servala Portal

The Servala Self-Service Portal

Latest release: 2026.07.15-0

Documentation

Available at https://docs.servala.com/.

The project documentation is written here: https://servala.app.codey.ch/servala/documentation.

Development setup

First, copy the .env.example file to .env and adjust the settings to your needs. Make sure to source the file before running any commands.

Then use uv to install the project and run its commands while youre developing:

just install-all
just run migrate
just run createcachetable
just run

This will start the development server on http://localhost:8000.

For testing mail sending, smtp4dev can be used:

docker run --rm -it -p 5000:80 -p 2525:25 docker.io/rnwood/smtp4dev

Configuration

Configuration happens using environment variables. See the available parameters in .env.example.

Custom Form Configuration

When defining custom forms for service definitions via form_config, certain commonly-used fields have default configurations available. These can be referenced by their field mapping without needing to specify all properties.

Default Field Configurations

Field Mapping Type Label Notes
display_name text Instance Name Required, max 100 characters
spec.parameters.service.fqdn array FQDNs Domain names for accessing the service
spec.parameters.instances number Instances Number of service instances (replicas)
spec.parameters.size.disk number Service storage size Displayed with "Gi" suffix, storage: true
spec.parameters.service.postgreSQLParameters.size.disk number PostgreSQL storage size Displayed with "Gi" suffix, storage: true

When a field in form_config uses one of these mappings, the default configuration is applied automatically. Any properties explicitly set in form_config will override the defaults.

Code style and linting

Servala uses several linters / formatters to keep the project style consistent for you. Run them like this:

just fmt

The repository features a pre-commit configuration which helps to properly format the source code before committing. It's recommended to install and use it.

Tests

Servala is tested via pytest. Run tests like this:

just test

This invokes pytest you can pass all pytest arguments here, too. Use just test-parallel to run tests in parallel.

Docker

The project provides a Dockerfile which builds a production-ready container image. It uses Caddy to serve static files and connect to Gunicorn, the Python WSGI application server.

Building:

docker build -t local/servala-portal .

Running:

docker run --rm -ti -p 8080:8080 --name=servala-portal --rm --env-file .env local/servala-portal
docker exec -it servala-portal uv run src/manage.py createsuperuser

Then access it with http://localhost:8080/ and the Django admin with http://localhost:8080/admin

Deployment

Deployment files are in the deployment/kustomize folder and makes use of Kustomize to account for differences between the deployment stages. Stages are configured with overlays in deployment/kustomize/overlays/$environment.

Resource Requests and Limits

Resources are configured to comply with APPUiO Cloud's memory-to-CPU ratio of 4096 MiB/core. See APPUiO Cloud documentation for details.

Production:

Container CPU Request Memory Request CPU Limit Memory Limit
servala 500m 2Gi 2 4Gi

Staging:

Container CPU Request Memory Request CPU Limit Memory Limit
servala 250m 1Gi 1 2Gi
ssh-tunnel-dev 50m 204Mi 100m 256Mi
ssh-tunnel-talos 50m 204Mi 100m 256Mi

Ratio Calculation:

The ratio is calculated as: Sum of Memory Requests / Sum of CPU Requests

  • Production: 2048 MiB / 0.5 cores = 4096 MiB/core
  • Staging: (1024 + 204 + 204) MiB / (0.25 + 0.05 + 0.05) cores = 1432 MiB / 0.35 cores = 4091 MiB/core

Staging

The code is automatically built and deployed on a push to the main branch. See .forgejo/workflows/build-deploy-staging.yaml for the actual workflow.

Production

Building and deployment for production happens when a Git tag is pushed. See .forgejo/workflows/build-deploy-prod.yaml for the actual workflow.

Versioning

We're using CalVer as the versioning scheme. The tool bumpver helps us to automate the process.

To cut a new release run the following command to check what will happen:

just release -d

The run the following command to create a release:

just release

Maintenance and management commands

You can interface with the Django server and project by running commands like this:

just run COMMAND

Useful commands:

  • migrate: Make sure database migrations are applied.
  • check --deploy: Runs checks, e.g. for missing or mismatched configuration, including custom servala configuration.
  • showmigrations: Show current database migrations status. Good for debugging.
  • runserver: Run development server (default command, runs when you run just just run)
  • clearsessions: Clear away expired user sessions. Runs automatically every week via the procrastinate background worker (just worker); the command remains available for manual runs.
  • reencrypt_fields: Run after you changed your SERVALA_SECRET_KEY or SERVALA_SALT_KEY in order to use the new keys, and be able to retire the previous ones.
  • make_staff_user: Mark one or multiple users as staff users. Use --substring flag to e.g. match entire email domains.
  • make_superuser: Mark one given user (by email address) as superuser.
  • export_data: Export configuration data as JSON for transport between environments.
  • import_data: Import configuration data from a JSON file exported by export_data.

Data export/import

The export_data and import_data commands allow transporting configuration data between environments (e.g. staging to production). They use natural keys (names, slugs) instead of database primary keys, so data can be imported into any environment regardless of existing IDs.

Supported models: cloudprovider, servicecategory, service, servicedefinition, serviceoffering, computeplan, controlplanecrd, computeplanassignment, organizationlimitprofile, organizationorigin

Export all models:

just run export_data -o data.json
# or to stdout for piping
just run export_data > data.json

Export specific models:

just run export_data service servicedefinition cloudprovider -o data.json

Import data:

just run import_data data.json

Dry run (validate without making changes):

just run import_data data.json --dry-run

Important notes:

  • Import uses update_or_create, so it is safe to run multiple times (idempotent).
  • The entire import runs in a single database transaction - it either fully succeeds or rolls back.
  • ControlPlane and BillingEntity are not exported because they contain environment-specific data (encrypted API credentials, Odoo references). They must already exist in the target environment and are referenced by name during import.
  • Image/logo files are not included in the export and must be transferred separately if needed.

Using AI Coding Agents

The project contains configuration for using Claude Code.

Usage recommendations:

  • laude Max with Opus 4.5 for best results
  • The obra/superpowers skills
  • Playwright MCP to have well integrated browser testing