CosmicAC Logo

CosmicAC Server Setup

Configure the server user, group, sudoers, Git, and rootless Docker required to run the CosmicAC application stack.

CosmicAC Server Setup

All application components run under the cosmicac user account. This guide covers creating that user, configuring access for team members, setting up Git, and installing rootless Docker.


Create the cosmicac User and Group

All application components will run under the cosmicac user account. Other team members can be added to the cosmicac group to manage PM2 and services.

# Create the cosmicac group
sudo groupadd cosmicac

# Create the user with home directory and add to cosmicac group
sudo useradd -m -s /bin/bash -g cosmicac cosmicac

# Set a password (optional, but recommended)
sudo passwd cosmicac

# Add to sudo group if needed for initial setup
sudo usermod -aG sudo cosmicac

Configure Sudoers for cosmicac Group

Create a sudoers file to allow members of the cosmicac group to run commands as the cosmicac user without a password. This enables PM2 management.

Create /etc/sudoers.d/cosmicac:

# Allow members of cosmicac group to run commands as cosmicac user
%cosmicac ALL=(cosmicac) NOPASSWD: ALL

# Allow members to switch to cosmicac user shell
%cosmicac ALL=(cosmicac) NOPASSWD: /bin/bash, /bin/sh

Apply the configuration:

# Create the sudoers file (must use visudo for safety)
sudo visudo -f /etc/sudoers.d/cosmicac

# Or create directly with proper permissions
echo '%cosmicac ALL=(cosmicac) NOPASSWD: ALL' | sudo tee /etc/sudoers.d/cosmicac
sudo chmod 440 /etc/sudoers.d/cosmicac

# Validate sudoers syntax
sudo visudo -c

Add Team Members to cosmicac Group

# Add existing users to cosmicac group
sudo usermod -aG cosmicac <username>

# Verify group membership
groups <username>

Managing PM2 as Team Member

Once added to the cosmicac group, team members can manage PM2:

# Run PM2 commands as cosmicac user
sudo -u cosmicac pm2 status
sudo -u cosmicac pm2 logs
sudo -u cosmicac pm2 restart all

# Switch to cosmicac user shell (for multiple commands)
sudo -u cosmicac bash -l

Verify User Setup

whoami   # Should output: cosmicac
echo $HOME   # Should output: /home/cosmicac

Configure Git

Set up Git to use HTTPS instead of SSH/git protocols and enable credential caching:

# Create/update .gitconfig
cat > ~/.gitconfig << 'EOF'
[url "https://github.com/"]
    insteadOf = git@github.com:
[url "https://"]
    insteadOf = git://
[credential]
    helper = cache --timeout=3600
EOF

This configuration:

  • Redirects git@github.com: URLs to HTTPS (avoids SSH key requirements)
  • Redirects git:// protocol URLs to HTTPS
  • Caches credentials for 1 hour (3600 seconds) to avoid repeated prompts

Verify the configuration:

cat ~/.gitconfig
git config --list | grep -E "(url|credential)"

Rootless Docker Setup

Rootless Docker allows containers to run without root privileges, improving security.

System-Level Configuration (Run as root/sudo)

Step 1: Update system and install prerequisites

sudo apt-get update && sudo apt-get upgrade -y

sudo apt-get install -y \
  curl \
  ca-certificates \
  gnupg \
  lsb-release \
  uidmap \
  dbus-user-session \
  fuse-overlayfs \
  slirp4netns \
  systemd-container \
  iproute2 \
  iptables

Step 2: Add Docker's official GPG key

sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

Step 3: Add Docker repository

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Step 4: Install Docker Engine

# Update apt with the new repository
sudo apt-get update

# Install Docker (includes dockerd-rootless-setuptool.sh)
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# Verify installation
docker --version

Troubleshooting: If you get "Package docker-ce has no installation candidate":

  1. Check your distribution: lsb_release -cs
  2. Verify the repository was added: cat /etc/apt/sources.list.d/docker.list
  3. Make sure you ran apt-get update after adding the repository

Step 5: Configure system for rootless Docker

Create sysctl configuration file /etc/sysctl.d/99-rootless-docker.conf:

# Enable user namespaces for rootless Docker
kernel.unprivileged_userns_clone=1

# Allow unprivileged users to bind to ports >= 80
net.ipv4.ip_unprivileged_port_start=80

# Increase the number of inotify watches
fs.inotify.max_user_watches=524288
fs.inotify.max_user_instances=512

# Network settings for better container networking
net.ipv4.ip_forward=1
net.ipv4.conf.all.route_localnet=1

Apply the configuration:

# Apply sysctl settings
sudo sysctl --system

# Set up subordinate UIDs and GIDs for cosmicac user (for user namespace mapping)
# Check if already configured, add only if not present
grep -q "^cosmicac:" /etc/subuid || echo "cosmicac:100000:65536" | sudo tee -a /etc/subuid
grep -q "^cosmicac:" /etc/subgid || echo "cosmicac:100000:65536" | sudo tee -a /etc/subgid

# Verify the entries
cat /etc/subuid
cat /etc/subgid

# Enable lingering (allows user services to run without login)
sudo loginctl enable-linger cosmicac

# Create XDG_RUNTIME_DIR for cosmicac user (required for systemd user session)
COSMICAC_UID=$(id -u cosmicac)
sudo mkdir -p /run/user/${COSMICAC_UID}
sudo chown cosmicac:cosmicac /run/user/${COSMICAC_UID}
sudo chmod 700 /run/user/${COSMICAC_UID}

# Disable system Docker daemon (we'll use rootless instead)
sudo systemctl disable --now docker.service docker.socket

User-Level Configuration (Run as cosmicac)

Switch to cosmicac user with proper systemd environment:

# Get cosmicac UID
COSMICAC_UID=$(id -u cosmicac)

# Switch to cosmicac with proper systemd environment
sudo -u cosmicac \
  XDG_RUNTIME_DIR=/run/user/${COSMICAC_UID} \
  DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/${COSMICAC_UID}/bus \
  bash -l

Once logged in as cosmicac:

# Verify environment variables are set
echo "XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR"
echo "UID=$(id -u)"

# If XDG_RUNTIME_DIR is empty, set it manually
export XDG_RUNTIME_DIR=/run/user/$(id -u)
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u)/bus

# Run rootless Docker setup
dockerd-rootless-setuptool.sh install

# Create service override for proper networking
mkdir -p ~/.config/systemd/user/docker.service.d
cat > ~/.config/systemd/user/docker.service.d/override.conf << 'EOF'
[Service]
Environment="DOCKERD_ROOTLESS_ROOTLESSKIT_DISABLE_HOST_LOOPBACK=false"
Environment="DOCKERD_ROOTLESS_ROOTLESSKIT_NET=slirp4netns"
Environment="DOCKERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER=builtin"
EOF

# Create Docker daemon config
mkdir -p ~/.config/docker
cat > ~/.config/docker/daemon.json << 'EOF'
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  },
  "default-address-pools": [
    {
      "base": "172.17.0.0/16",
      "size": 24
    }
  ]
}
EOF

# Set environment variables (add to .bashrc)
cat >> ~/.bashrc << 'EOF'

# Rootless Docker configuration
export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock
export PATH=$HOME/bin:$PATH
EOF

# Source the environment
source ~/.bashrc

# Enable and start Docker for this user
systemctl --user enable docker
systemctl --user start docker

# Verify installation
docker --version
docker compose version

# Test Docker networking
docker run --rm alpine echo "Docker networking test successful!"

Verify Rootless Docker

# Check Docker daemon status
systemctl --user status docker

# Check Docker socket exists
ls -la /run/user/$(id -u)/docker.sock

# Test port binding
docker run --rm -d -p 8888:80 --name test-nginx nginx:alpine
sleep 2
curl -s http://localhost:8888 && echo "Port binding works!"
docker stop test-nginx

On this page