Skip to content

Persistent Docker Login Setup

Problem

Docker login to GitLab Container Registry expires periodically, requiring manual re-authentication on the VPS.

Solution

Set up automatic Docker login refresh using: 1. Secure credential storage - Credentials stored in a protected file 2. Automatic refresh - Cron job refreshes login daily 3. Manual refresh script - Can be called anytime

Setup

Step 1: Run Setup Script

On the VPS:

cd /opt/po-platform
./infrastructure/scripts/setup-persistent-docker-login.sh

The script will: 1. Prompt for GitLab username and Personal Access Token 2. Store credentials securely in .docker-registry-credentials (readable only by owner) 3. Perform initial login 4. Set up a cron job to refresh login daily at 2 AM

Step 2: Create GitLab Personal Access Token

If you don't have a token:

  1. Go to GitLab → SettingsAccess Tokens
  2. Create a new token with:
  3. Name: Docker Registry VPS (or any name)
  4. Scopes: read_registry (minimum required)
  5. Expiration: Set to no expiration (or very long, e.g., 10 years)
  6. Copy the token immediately (you won't see it again)

Important: Use a token with no expiration or very long expiration to avoid frequent updates.

How It Works

Credential Storage

Credentials are stored in:

/opt/po-platform/.docker-registry-credentials

Permissions: 600 (read/write for owner only)

Format:

REGISTRY_USER=your-username
REGISTRY_PASSWORD=your-personal-access-token

Automatic Refresh

A cron job runs daily at 2 AM:

0 2 * * * /opt/po-platform/infrastructure/scripts/refresh-docker-login.sh

Logs: /opt/po-platform/logs/docker-login-refresh.log

Manual Refresh

You can refresh login manually anytime:

cd /opt/po-platform
./infrastructure/scripts/refresh-docker-login.sh

Verification

Check Current Login Status

# Check if logged in
docker pull registry.gitlab.com/portugalodissey/po-platform/api-gateway:latest

# Or check config
cat ~/.docker/config.json | grep -A 5 "registry.gitlab.com"

Check Cron Job

# List cron jobs
crontab -l | grep docker-login

# Check logs
tail -f /opt/po-platform/logs/docker-login-refresh.log

Test Refresh Script

# Run refresh manually
./infrastructure/scripts/refresh-docker-login.sh

# Should output:
# 2025-11-27 14:30:00: ✅ Docker login refreshed successfully

Updating Credentials

If you need to update credentials:

cd /opt/po-platform

# Option 1: Delete and re-run setup
rm .docker-registry-credentials
./infrastructure/scripts/setup-persistent-docker-login.sh

# Option 2: Edit manually (not recommended)
nano .docker-registry-credentials
chmod 600 .docker-registry-credentials
./infrastructure/scripts/refresh-docker-login.sh

Removing Persistent Login

To remove the persistent login setup:

# Remove cron job
crontab -e
# Delete the line with refresh-docker-login.sh

# Remove credentials file (optional)
rm /opt/po-platform/.docker-registry-credentials

# Remove refresh script (optional)
rm /opt/po-platform/infrastructure/scripts/refresh-docker-login.sh

Troubleshooting

Login Still Expires

Possible causes: 1. Cron job not running 2. Credentials file permissions incorrect 3. Token expired (if not set to no expiration)

Fix:

# Check cron service
systemctl status cron

# Verify cron job exists
crontab -l | grep docker-login

# Check script permissions
ls -l infrastructure/scripts/refresh-docker-login.sh

# Test script manually
./infrastructure/scripts/refresh-docker-login.sh

Permission Denied

If you get permission errors:

# Ensure credentials file has correct permissions
chmod 600 .docker-registry-credentials

# Ensure script is executable
chmod +x infrastructure/scripts/refresh-docker-login.sh

Cron Job Not Running

# Check cron logs
grep CRON /var/log/syslog | tail -20

# Verify cron service is running
systemctl status cron

# Restart cron if needed
systemctl restart cron

Security Best Practices

  1. Use Personal Access Token with minimal scope (read_registry only)
  2. Set token to no expiration (or very long expiration)
  3. Store credentials file with 600 permissions (owner read/write only)
  4. Don't commit credentials file (already in .gitignore)
  5. Rotate token if compromised (delete old token, create new one)

Alternative: Using Docker Credential Helper

For more advanced setups, you can use Docker credential helpers:

# Install credential helper (example for pass)
apt-get install docker-credential-helpers

# Configure Docker to use credential helper
mkdir -p ~/.docker
echo '{"credsStore": "pass"}' > ~/.docker/config.json

However, the cron-based approach is simpler and sufficient for most use cases.