No description
  • PHP 84.3%
  • CSS 15.2%
  • JavaScript 0.5%
Find a file
Nicky Hendriks 17f65bed9e
All checks were successful
Build and deploy / deploy (push) Successful in 1s
feat: add sudo to privileged commands for forgejo runner
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 22:26:23 +02:00
.forgejo/workflows feat: add sudo to privileged commands for forgejo runner 2026-04-07 22:26:23 +02:00
i18n Add dynamic workflows and roles management 2026-04-07 18:37:02 +02:00
lib Add dynamic workflows and roles management 2026-04-07 18:37:02 +02:00
public Add dynamic workflows and roles management 2026-04-07 18:37:02 +02:00
templates Add dynamic workflows and roles management 2026-04-07 18:37:02 +02:00
bak.gitignore Temp disable .gitignore 2026-04-06 07:29:19 +02:00
bootstrap.php Temp disable .gitignore 2026-04-06 07:29:19 +02:00
CLAUDE.md Add dynamic workflows and roles management 2026-04-07 18:37:02 +02:00
config.example.php Initial commit, right folders 2026-04-05 22:44:00 +02:00
config.php Temp disable .gitignore 2026-04-06 07:29:19 +02:00
infra-portal.zip Initial commit 2026-04-05 22:42:28 +02:00
README.md Initial commit, right folders 2026-04-05 22:44:00 +02:00

Expeditioner Infrastructure Portal

PHP 8.3 + MySQL-free web portal for managing the exped_ansible Ansible repository. Runs on boromir at /var/www/domains/exped.nu/infra.exped.nu/.

Requirements

  • PHP 8.1+ with curl and exec() enabled
  • Apache with mod_rewrite and mod_headers
  • The www-data user (or whichever user Apache runs as) needs read/write access to /var/forgejo/exped_ansible/
  • Git must be available in the PATH that PHP's exec() uses (/usr/bin/git)

Directory layout

infra.exped.nu/
├── bootstrap.php          # Loaded by every page: config, session, i18n, auth
├── config.php             # YOUR secrets — gitignored, never committed
├── config.example.php     # Template — commit this
├── .gitignore
├── i18n/
│   └── en.php             # All UI strings — add nl.php for Dutch
├── lib/
│   ├── ForgejoApi.php     # Forgejo REST API client
│   ├── GitRepo.php        # Git operations via shell
│   └── Inventory.php      # hosts.yml and host_vars read/write
├── templates/
│   └── layout.php         # Shared HTML shell (sidebar, topbar)
└── public/                # Apache DocumentRoot points here
    ├── index.php           # Redirects to dashboard or login
    ├── login.php
    ├── logout.php
    ├── dashboard.php
    ├── workflows.php
    ├── runs.php
    ├── inventory.php
    ├── hostvars.php
    ├── groupvars.php
    ├── hostsyml.php
    ├── newlocation.php
    ├── .htaccess
    ├── api/
    │   └── job_log.php    # AJAX endpoint: proxy Forgejo job logs
    ├── css/
    │   └── portal.css
    ├── js/
    │   └── portal.js
    └── fonts/
        └── CHARCUTERIE-BLOCK-W05-REGULAR.TTF   ← drop your font here

Installation

1. Clone or unzip

cd /var/www/domains/exped.nu/
# unzip or git clone into infra.exped.nu/

2. Drop in the font

cp /path/to/CHARCUTERIE-BLOCK-W05-REGULAR.TTF \
   /var/www/domains/exped.nu/infra.exped.nu/public/fonts/

3. Create config.php

cd /var/www/domains/exped.nu/infra.exped.nu/
cp config.example.php config.php
$EDITOR config.php

Generate a password hash:

php -r "echo password_hash('yourpassword', PASSWORD_BCRYPT) . PHP_EOL;"

Generate a session secret:

php -r "echo bin2hex(random_bytes(32)) . PHP_EOL;"

4. Apache vhost

<VirtualHost *:443>
    ServerName infra.exped.nu
    DocumentRoot /var/www/domains/exped.nu/infra.exped.nu/public

    <Directory /var/www/domains/exped.nu/infra.exped.nu/public>
        AllowOverride All
        Require all granted
    </Directory>

    # Deny direct access to everything outside public/
    <Directory /var/www/domains/exped.nu/infra.exped.nu>
        Require all denied
    </Directory>
    <Directory /var/www/domains/exped.nu/infra.exped.nu/public>
        Require all granted
    </Directory>

    SSLEngine on
    # ... your cert config (Nginx Proxy Manager handles this via mithrandir)
</VirtualHost>

If you're terminating SSL on mithrandir (Nginx Proxy Manager) and proxying to boromir, just point the proxy at http://boromir:80 and set DocumentRoot as above with a plain HTTP vhost.

5. Git permissions

The web user needs to be able to run git commands in the repo:

# Option A: chown the repo to www-data
chown -R www-data:www-data /var/forgejo/exped_ansible/

# Option B: add www-data to the forgejo group (if the repo is owned by a forgejo user)
usermod -aG forgejo www-data

# Make sure git is in the exec PATH for PHP
which git   # should return /usr/bin/git

Also set git identity in the repo so commits work even without a global ~/.gitconfig:

cd /var/forgejo/exped_ansible
git config user.name  "Expeditioner Portal"
git config user.email "infra@exped.nu"

The portal overrides this per-commit via -c user.name= anyway, but having it set locally avoids edge cases.

6. SSH key for git push

The www-data user needs an SSH key that has push access to forgejo.exped.nu:

# Create a key for www-data
sudo -u www-data ssh-keygen -t ed25519 -C "infra-portal@boromir" -f /var/www/.ssh/id_ed25519 -N ""

# Show the public key — add this to Forgejo under the Expeditioner org or as a deploy key
sudo cat /var/www/.ssh/id_ed25519.pub

# Test
sudo -u www-data ssh -T git@forgejo.exped.nu

Make sure the repo remote uses SSH:

cd /var/forgejo/exped_ansible
git remote get-url origin
# Should be: git@forgejo.exped.nu:Expeditioner/exped_ansible.git
# If it's https, change it:
git remote set-url origin git@forgejo.exped.nu:Expeditioner/exped_ansible.git

Adding Dutch translations

cp i18n/en.php i18n/nl.php
# Translate the values in nl.php

Then set 'default_lang' => 'nl' in config.php.

Forgejo API token

In Forgejo: Settings → Applications → Generate Token. Needs scopes: read:repository, write:repository (for contents), read:actionsuser (for workflow runs).

Or at the org level: Expeditioner org → Settings → Applications.