Files
ermnvldmr.com/services/docs/content/en/root/guides/first-node.md
T

5.3 KiB

title, description, weight
title description weight
Setting Up Your First Node A practical guide on creating your first node and hooking up the deployment commons. 25

Goal: Create a configuration repository for your infrastructure, add the root deployment commons as a submodule, and define your first basic node.

1. Creating the Configuration Repository

Your infrastructure should be managed from a single Git repository. This repository will hold the configuration for all your servers (nodes).

{{% steps %}}

Step 1: Initialize the repository

Create a new directory and initialize Git.

mkdir my-infrastructure
cd my-infrastructure
git init

Step 2: Add the commons submodule

The ermnvldmr.com-root-commons must be placed at .operator/shared.

mkdir -p .operator
git submodule add https://github.com/deytenit/ermnvldmr.com-root-commons.git .operator/shared

Step 3: Create the Bootstrap Script

Create an init.sh file at the root of your repository. This script links the commons framework into your local environment.

#!/usr/bin/env bash
# init.sh

# Source common utilities from the submodule
source "$(git -C "$(dirname "$0")" rev-parse --show-toplevel)/.operator/shared/scripts/lib/common.sh"

SCRIPT_NAME="init"

navigate_to_repo_root

log_info "Setting up Git hooks..."
git config core.hooksPath .operator/shared/githooks
git config --global --add safe.directory "${REPO_ROOT}"

log_info "Setting up PATH for the root dispatcher..."
ABSOLUTE_RUN_DIR="$(realpath "${REPO_ROOT}/.operator/shared/scripts/run")"
BASHRC_ENTRY="export PATH=\"${ABSOLUTE_RUN_DIR}:\$PATH\""

sed -i '/\.operator\/shared\/scripts\/run/d' ~/.bashrc
echo "$BASHRC_ENTRY" >> ~/.bashrc
log_info "Done. Please run 'source ~/.bashrc' or re-login to your shell."

Make it executable:

chmod +x init.sh

{{% /steps %}}

2. Defining Your First Node

A Node is a folder at the repository root that represents one physical or virtual server.

Node Structure

Let's create a node named daedalus. Inside, we'll define an operator configuration (e.g., for backups) and a core service.

mkdir -p daedalus/.operator/configs/{cron,crowdsec,systemd,ufw/docker,ufw/host}
mkdir -p daedalus/root

Base Configurations (Optional)

You can place configuration files (like UFW rules or a crontab) inside the daedalus/.operator/configs/ directory. For example, a basic crontab:

# Run backups every night at 3:00 AM
0 3 * * * root sync tiers daedalus

3. Configuring Services (Docker Compose)

The framework relies on docker-compose.yml to orchestrate services.

Node-Level Infrastructure (Operator)

The daedalus/docker-compose.yml file runs infrastructure utilities, such as restic for backups or VPN agents. This compose file has direct access to the filesystem via @tierX mounts.

name: 'operator'

services:
  restic:
    image: restic/restic:0.18.1
    container_name: operator-restic
    volumes:
      # Example: mounting project data for backups (Read-Only)
      - ./@tier2/my-app/data:/data/@tier2/my-app/data:ro
      - ./@tier3/.operator/restic/cache:/var/restic-cache
    environment:
      RESTIC_REPOSITORY: "s3:example.com/my-bucket/daedalus"
      RESTIC_PASSWORD: "${RESTIC_PASSWORD?error}"
      # AWS credentials...
    network_mode: "host"
    entrypoint: [ "restic" ]

The Root Project

The root project typically contains your reverse proxies (Traefik) and core services that other projects will route through.

name: root

services:
  socket-proxy:
    image: tecnativa/docker-socket-proxy:0
    container_name: root-socket-proxy
    user: "0:0"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      CONTAINERS: 1
      SERVICES: 1
      TASKS: 1
    networks:
      socket: {}
    restart: unless-stopped

  traefik:
    image: traefik:3.6
    container_name: root-traefik
    # UID and GID are automatically populated by the framework after running 'root tiers useradd'
    user: "${UID?error}:${GID?error}"
    group_add:
      - "${SHARED_GID?error}"
    depends_on:
      - socket-proxy
    volumes:
      - ./@tier1/shared/root/traefik/letsencrypt:/letsencrypt
      - ./@tier3/traefik/logs:/logs
      - ./@tier1/traefik/dynamic:/etc/traefik/dynamic:ro
    ports:
      - '0.0.0.0:80:80'
      - '0.0.0.0:443:443'
    networks:
      proxy: {}
      socket: {}
    command:
      - "--api.dashboard=true"
      - "--providers.docker=true"
      - "--providers.docker.network=root-proxy"
      - "--providers.docker.endpoint=tcp://root-socket-proxy:2375"
    restart: unless-stopped

networks:
  proxy:
    name: root-proxy
    internal: true
    driver: bridge
  socket:
    name: root-socket
    internal: true
    driver: bridge

4. Deployment

Now that your structure is ready:

  1. Commit and push this repository to your Git server (e.g., GitHub).
  2. SSH into your VPS.
  3. Follow the Installation guide, using your new repository URL instead of the example ones.

See also: