Skip to content

Setup

Deployment using Docker/Nginx

INJECT Exercise Platform provides a simplified deployment method via Docker Compose. This method simplifies the deployment by creating necessary settings and pairings between the frontend and backend. It also creates a singular endpoint for accessing IXP.

Docker Setup

This solution consists of 5 containers: frontend, backend, redict, database and reverse proxy server. Frontend and backend are set up to communicate under a single endpoint handled by the reverse-proxy server (Nginx). PostgreSQL database handles the management of user/exercise data. Redict is used to allow multiple workers on the backend. User-uploaded files, images and definition-related content are stored on the backend. The reverse proxy forwards requests either to frontend or backend.

Deployment is set up with persistent storage under two Docker Compose volumes called inject-data and inject-pgdata. This volume contains any data generated by IXP and the current configuration of the platform. At the current state, the platform can be effectively backed up, assuming you back up both volumes and the INJECT_SECRET_KEY environment variable.

(Optional) Configuring Rootless Docker for Proper Client IP Logging

If you are using Rootless Docker and want to ensure that backend logs correctly reflect the client's IP address, you need to make the following changes. Without these adjustments, backend logs may display incorrect IP addresses, usually showing internal Docker addresses instead of the actual requester's IP. This configuration is required only for Rootless Docker; it is not needed for standard Docker.

Step 1: Update packages

Ensure all necessary packages are updated while running as the root user. This step ensures that all dependencies are up to date and compatible with the required configurations.

Step 2: Modify System Configuration

Since Rootless Docker operates without root privileges, you need to adjust the network-level driver for the user-level docker.service in systemd to allow proper traffic routing. To do this, create or update the following override configuration file ~/.config/systemd/user/docker.service.d/override.conf with the following content:

[Service]
Environment="DOCKERD_ROOTLESS_ROOTLESSKIT_NET=slirp4netns"
Environment="DOCKERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER=slirp4netns"

Also, add net.ipv4.ip_unprivileged_port_start=0 to /etc/sysctl.conf (or /etc/sysctl.d) and run sudo sysctl --system.

Step 3: Restart Docker Daemon

Once all the above configurations are in place, reload and restart the Docker daemon to apply the changes:

systemctl --user daemon-reload
systemctl --user restart docker

Step 4: Update Nginx Configuration

To allow Nginx to properly resolve the internal Docker network and access external client IPs, add the following lines under your Nginx service definition in the compose.yml file:

nginx:
  ...
  extra_hosts:
    - "host.docker.internal:host-gateway"
  ports:
    - target: 80
      published: 80
      protocol: tcp
      mode: host
    - target: 443
      published: 443
      protocol: tcp
      mode: host
  ...

This configuration ensures that the container correctly forwards traffic to and from the host machine and that Nginx can resolve the host-gateway address, allowing it to properly reflect the external IP addresses of incoming requests.

Environment Variables

All the technical configuration is done with environment variables. Most are prefixed under INJECT_. Some additional variables are included; however, these are inferred from the INJECT_ prefixed environment variables, which means that these do not have to be changed manually.

The available variables are listed below:

Domain & Security

  • INJECT_DOMAIN – The domain name where your IXP instance will be accessible (e.g., example.com).
  • INJECT_HOMEPAGE – URL of the homepage or landing page for your IXP instance.
  • INJECT_SECRET_KEY – A cryptographically secure string (minimum 50 characters) used for signing and securing sessions. Keep this value private.
  • INJECT_HOST_ADDRESSES – Comma-separated list of hostnames or IP addresses permitted to access the backend (e.g., example.com,www.example.com).
  • VITE_HTTPS_HOST – The HTTPS URL or hostname that the frontend should use to connect to the backend service.
  • CORS_ALLOWED_ORIGINS – Comma-separated list of origins allowed for Cross-Origin Resource Sharing (CORS), enabling secure API access from specified domains.
  • INJECT_REQUEST_TIMEOUT – A number of seconds which should be set as the timeout value in NGINX.

Email Configuration

  • INJECT_EMAIL_HOST – The SMTP server address used for sending emails (e.g., smtp.mailprovider.com).
  • INJECT_EMAIL_PORT – Port number for connecting to the SMTP server (commonly 25 for unencrypted, 465 for SSL, and 587 for TLS).
  • INJECT_EMAIL_HOST_USER – Username for authenticating with the SMTP server.
  • INJECT_EMAIL_HOST_PASSWORD – Password for the SMTP server user account. Used together with INJECT_EMAIL_HOST_USER.
  • INJECT_EMAIL_SENDER_ADDRESS – Email address that appears as the sender in automated emails from the platform.
  • INJECT_EMAIL_PROTOCOL – (Optional) Protocol for SMTP communication: ssl or tls (case-insensitive). Leave unset for unencrypted connections.

Logging

  • INJECT_LOGS – Filesystem path where application logs will be stored (e.g., /var/log/inject.log).

Database

  • INJECT_DB_HOST – Hostname or IP address of the PostgreSQL database server.
  • INJECT_DB_USER – Username for connecting to the database.
  • INJECT_DB_PASS – Password for the database user.
  • INJECT_DB_MAX_CONNECTIONS – Sets the maximum number of connections that PostgreSQL can accept. Approximate formula for how many connections will be used: 2 x INJECT_WORKER_COUNT + maximum expected running synchronous exercise count + maximum expected running team count in on-demand exercises. For example, with 8 workers, 5 running synchronous exercises and 3 on-demand exercises with 20 teams each, the minimum number of connections is 81. It is recommended to leave some headroom.

Redict (Backend Worker Management)

  • INJECT_REDICT_HOST – Host address for the Redict service. Set to enable Redict for backend worker management.
  • INJECT_WORKER_COUNT – Number of backend worker processes to spawn. Adjust for optimal performance based on available resources.

OpenSearch Integration

  • INJECT_OPENSEARCH_HOST – Host address for the OpenSearch service. Set to enable OpenSearch integration.
  • VITE_OPENSEARCH_HOST – OpenSearch host address exposed to frontend clients.
  • INJECT_OPENSEARCH_PORT – Port number for connecting to the OpenSearch service.
  • VITE_OPENSEARCH_PORT – OpenSearch port number exposed to frontend clients.
  • INJECT_OPENSEARCH_USER – Username for authenticating with OpenSearch.
  • INJECT_OPENSEARCH_PASSWORD – Password for the OpenSearch user account.

LLM (Large Language Model) Integration

The following variables need to be set if you want to use the LLM platform features. Otherwise, these values are not needed.

  • INJECT_LLM_URL – The full HTTP endpoint where the platform sends LLM requests. For example:
    • http://192.0.2.1:8000/v1/chat/completions – self-hosted without a domain (illustration values)
    • https://mydomain.com/v1/my-llm-api/chat – self-hosted with a domain, or a cloud provider URL (illustration values)
    • https://generativelanguage.googleapis.com/v1beta/openai/chat/completions – cloud provider URL (example of a Google Gemini OpenAI-compatible endpoint)
  • INJECT_LLM_MODEL – The specific model identifier string (ID) to be requested. E.g., gpt-4o, gemini-1.5-flash, llama3.2, qwen2.5-72b-instruct.
  • INJECT_LLM_API_KEY_HEADER – The HTTP header used for authentication (usually Authorization or x-api-key).
  • INJECT_LLM_API_KEY_VALUE – The actual key/token value for authentication. The format depends on the required HTTP header:
    • Standard 'Authorization' Header: You must include the Bearer prefix.
      • Example: Bearer secret-value-784sderrddpiaqmv
    • Custom Header (e.g., x-api-key): Enter the raw key only.
      • Example: just-secret-value-zsmgzwvvfghe42
  • INJECT_LLM_TIMEOUT – Time (in seconds) the INJECT backend server waits for a response from the LLM before cancelling. 60 seconds is set as the default. If you want to increase the time, you must also increase the INJECT_REQUEST_TIMEOUT.

You can use the default .env file to set up your configuration. Such a file is included both in the Let's Encrypt and self-provided certificate setup guides.