gitops: public-safe values, docs; remove legacy app/resources

- Sanitize placeholders, centralize values under gitops/values/
- Argo Application placeholder repoURL; env-example + observability.yaml
- Remove Swarm app/, resources/, install.sh; add root README

Made-with: Cursor
This commit is contained in:
timotheereausanofi
2026-03-20 12:25:01 +01:00
parent 3e5dfaa1cb
commit 5e120c4d74
87 changed files with 397 additions and 3263 deletions

11
README.md Normal file
View File

@@ -0,0 +1,11 @@
# OneLab (Kubernetes)
Deploy OneLab with **Argo CD** and Helm using the manifests under [`gitops/`](gitops/).
**Documentation:** [gitops/README.md](gitops/README.md) — prerequisites, configuration, bootstrap, and troubleshooting.
```bash
kubectl apply -f gitops/argocd/application.yaml
```
Edit `gitops/argocd/application.yaml` (`repoURL`, `targetRevision`) and `gitops/values/*.yaml` before syncing in production.

View File

@@ -1,3 +0,0 @@
#!/bin/bash
ANSIBLE_LOG_PATH=./logs/ansible/$(date +%F)-ansible.log ansible-playbook ./installation/1.27.0/app/playbooks/backup.yml

View File

@@ -1,154 +0,0 @@
---
onelab:
domain: https://localhost
logs:
# path: "/path/to/onelab/logs"
level: info
assets:
# path: "/path/to/onelab/data"
purge: 1d
shared:
inputs:
path: "./data/shared/inputs"
archive_path: "./data/shared/archived"
security:
cors: '*'
auth:
token:
expiration: 5m
key: TokenAuthPlaceholder
password:
expiration: 90d
min_length: 8
prevent_reuse: 5
allow_list: []
block_list: []
authentifier: "email"
ratelimit:
ip:
max: 1000
duration: 1d
auth:
max: 5
duration: 5m
delay_after: 2
delay_ms: 1000
devices:
cors: '*'
monitoring:
token: TokenMonitoringPlaceholder
params:
session:
idle: 45m
remember_me: true
lab:
creation_policy: many
# compliance:
# require_electronic_signature: true
# execution_operator_restriction_policy: 'reviewed'
# execution_admin_expert_restriction_policy: 'reviewed'
# prevent_csv_import: true
# prevent_manual_metadata_edit: true
# device_restart: true
signup: false
# Google Analytics
# ga: XXXXX
# Intercom Andrew Alliance
intercom:
appid: zxvgsagz
secret: QUw2jEV8utIpe9DeYjOqBjhBY9VxjXddKUCISUNu
# Recaptcha Andrew Alliance
# recaptcha:
# client: XXXXXXXXXXXX
# secret: XXXXXXXXXXXX
#links:
# terms: https://www.andrewalliance.com/onelab-service-agreement.pdf
# privacy: https://www.andrewalliance.com/onelab-privacy-policy.pdf
# cookies: https://www.andrewalliance.com/onelab-cookie-policy.pdf
mailer:
#
# SMTP
# smtp:
# host: XXX (optional)
# port: XXX (optional)
# auth: (optional)
# user: XXX
# pass: XXX
# type: custom | login | oauth2 (optional)
# method: XXX (optional)
# secure: true | false (optional)
#
# Amazon SES
# ses:
# accessKeyId: XXXX
# secretAccessKey: XXXX
#
# MailGun
# mailgun:
# auth:
# api: XXXX
# domain: XXXX
#
# Debug
# debug:
# type: file | mail
# path: XXXX
# redirect: XXX@andrewalliance.com
#
noreply: no-reply@andrewalliance.com
queue:
scheduling: 15
maxsize: 50
error:
maxtries: 3
timeout: 60
ldap:
enabled: false
# timeout: 10
# encryption: plain | tls | start_tls
# policy: all | changes_only
# verify_certificates: true | false
# tls:
# ca: file_path
# cert: file_path
# key: file_path
# ciphers: string
# ssl_version: string
services:
db:
# host: db
# Note: port 5432 is the standard port for postgres however a custom port can be used if 5432 is occupied already
# port: 5432
database: postgres
username: postgres
password: DBPasswordPlaceholder
schema: onelab
# replicas: 1
# redis:
# host: redis
# port: '6379'
# replicas: 1
rabbit:
# url: rabbitmq
# port: 5671
token: TokenRabbitPlaceholder
# replicas: 1
api:
replicas: 2
# apidevice:
# replicas: 1
# apirabbit:
# replicas: 1
# devices:
# replicas: 1
# experiments:
# replicas: 1
# images:
# replicas: 1
# manual:
# replicas: 1
# website:
# ssr: false
# ws:
# replicas: 1

View File

@@ -1,319 +0,0 @@
version: "3.3"
services:
# If the database isn't accessed other than by services present in this file, remove port instruction.
# It exposes the database to the host system and if the server isn't secure, it exposes the database to attacks.
# That doesn't exclude the need to secure the servers on which the containers are run.
db:
image: hub.andrewalliance.com/releases/postgres:17.8
volumes:
- pgdata:/var/lib/postgresql/data
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD={{ onelab.services.db.password }}
- POSTGRES_DB=postgres
{% if onelab.services.db.port is defined %}
ports:
- "{{ onelab.services.db.port }}:5432"
{% endif %}
deploy:
replicas: {{ onelab.services.db.replicas|default('1') }}
placement:
constraints:
- node.role == manager
redis:
image: hub.andrewalliance.com/releases/redis:7.4.7-alpine
deploy:
replicas: {{ onelab.services.db.redis.replicas|default('1') }}
placement:
constraints:
- node.role == manager
rabbitmq:
image: hub.andrewalliance.com/releases/rabbitmq:3.13.7
hostname: "onelab"
volumes:
- rabbitmq_data:/var/lib/rabbitmq/mnesia
configs:
- source: enable_plugins
target: /etc/rabbitmq/enabled_plugins
- source: rabbit.conf
target: /etc/rabbitmq/rabbitmq.conf
- source: advanced.conf
target: /etc/rabbitmq/advanced.conf
- source: definitions.json
target: /opt/definitions.json
- source: rabbit.crt
target: /etc/rabbitmq/ssl/rabbit.crt
- source: rabbit.key
target: /etc/rabbitmq/ssl/rabbit.key
- source: rabbit.fullchain.pem
target: /etc/rabbitmq/ssl/rabbit.fullchain.pem
ports:
- "5671:5671"
deploy:
replicas: {{ onelab.services.rabbit.replicas|default('1') }}
placement:
constraints:
- node.role == manager
supervisor:
image: hub.andrewalliance.com/releases/onelab-supervisor-worker:1.27.0
volumes:
- {{ onelab.logs.path|default('./logs') }}:/logs
- {{ onelab.assets.path|default('./data') }}:/data
configs:
- source: configurations.yml
target: /conf/configurations.yml
deploy:
replicas: 1
placement:
constraints:
- node.role == {{ deploy_on|default('manager') }}
file-worker:
image: hub.andrewalliance.com/releases/onelab-file-worker:1.27.0
volumes:
- {{ onelab.logs.path|default('./logs') }}:/logs
- {{ onelab.assets.path|default('./data') }}:/data
- {{ onelab.shared.inputs.path|default('./data/shared/inputs') }}:/shared-inputs
- {{ onelab.shared.inputs.archived_path|default('./data/shared/archived') }}:/shared-archived
configs:
- source: configurations.yml
target: /conf/configurations.yml
deploy:
replicas: 1
placement:
constraints:
- node.role == manager
api:
image: hub.andrewalliance.com/releases/onelab-api:1.27.0
volumes:
- {{ onelab.logs.path|default('./logs') }}:/logs
- {{ onelab.assets.path|default('./data') }}:/data
configs:
- source: configurations.yml
target: /conf/configurations.yml
deploy:
replicas: {{ onelab.services.api.replicas|default('1') }}
placement:
constraints:
- node.role == {{ deploy_on|default('manager') }}
api-device:
image: hub.andrewalliance.com/releases/onelab-api-device:1.27.0
volumes:
- {{ onelab.logs.path|default('./logs') }}:/logs
- {{ onelab.assets.path|default('./data') }}:/data
configs:
- source: configurations.yml
target: /conf/configurations.yml
deploy:
replicas: {{ onelab.services.apidevice.replicas|default('1') }}
placement:
constraints:
- node.role == {{ deploy_on|default('manager') }}
api-rabbit:
image: hub.andrewalliance.com/releases/onelab-api-rabbit:1.27.0
volumes:
- {{ onelab.logs.path|default('./logs') }}:/logs
- {{ onelab.assets.path|default('./data') }}:/data
configs:
- source: configurations.yml
target: /conf/configurations.yml
deploy:
replicas: {{ onelab.services.apirabbit.replicas|default('1') }}
placement:
constraints:
- node.role == {{ deploy_on|default('manager') }}
devices-worker:
image: hub.andrewalliance.com/releases/onelab-devices-worker:1.27.0
volumes:
- {{ onelab.logs.path|default('./logs') }}:/logs
- {{ onelab.assets.path|default('./data') }}:/data
configs:
- source: configurations.yml
target: /conf/configurations.yml
deploy:
replicas: {{ onelab.services.devices.replicas|default('1') }}
placement:
constraints:
- node.role == {{ deploy_on|default('manager') }}
experiments-worker:
image: hub.andrewalliance.com/releases/onelab-experiments-worker:1.27.0
volumes:
- {{ onelab.logs.path|default('./logs') }}:/logs
configs:
- source: configurations.yml
target: /conf/configurations.yml
deploy:
replicas: {{ onelab.services.experiments.replicas|default('1') }}
placement:
constraints:
- node.role == {{ deploy_on|default('manager') }}
images-worker:
image: hub.andrewalliance.com/releases/onelab-images-worker:1.27.0
volumes:
- {{ onelab.logs.path|default('./logs') }}:/logs
- {{ onelab.assets.path|default('./data') }}:/data
configs:
- source: configurations.yml
target: /conf/configurations.yml
deploy:
replicas: {{ onelab.services.images.replicas|default('1') }}
placement:
constraints:
- node.role == {{ deploy_on|default('manager') }}
{% if (onelab.ldap|default(false)) != false %}
ldap-worker:
image: hub.andrewalliance.com/releases/onelab-ldap-worker:1.27.0
volumes:
- {{ onelab.logs.path|default('./logs') }}:/logs
configs:
- source: configurations.yml
target: /conf/configurations.yml
{% if onelab.ldap.tls.ca is defined %}
- source: ldap-ca.crt
target: /ldap/ca.crt
{% endif %}
{% if onelab.ldap.tls.key is defined %}
- source: ldap-private.key
target: /ldap/private.key
{% endif %}
{% if onelab.ldap.tls.cert is defined %}
- source: ldap-cert.crt
target: /ldap/cert.crt
{% endif %}
deploy:
replicas: {{ onelab.services.ldap.replicas|default('1') }}
placement:
constraints:
- node.role == {{ deploy_on|default('manager') }}
{% endif %}
{% if (onelab.mailer.smtp|default(false)) != false or (onelab.mailer.ses|default(false)) != false %}
mailer-worker:
image: hub.andrewalliance.com/releases/onelab-mailer-worker:1.27.0
volumes:
- {{ onelab.logs.path|default('./logs') }}:/logs
configs:
- source: configurations.yml
target: /conf/configurations.yml
deploy:
replicas: {{ onelab.services.mailer.replicas|default('1') }}
placement:
constraints:
- node.role == {{ deploy_on|default('manager') }}
{% endif %}
manual-worker:
image: hub.andrewalliance.com/releases/onelab-manual-worker:1.27.0
volumes:
- {{ onelab.logs.path|default('./logs') }}:/logs
configs:
- source: configurations.yml
target: /conf/configurations.yml
deploy:
replicas: {{ onelab.services.manual.replicas|default('1') }}
placement:
constraints:
- node.role == {{ deploy_on|default('manager') }}
websocket-worker:
image: hub.andrewalliance.com/releases/onelab-websocket-worker:1.27.0
volumes:
- {{ onelab.logs.path|default('./logs') }}:/logs
configs:
- source: configurations.yml
target: /conf/configurations.yml
deploy:
replicas: {{ onelab.services.ws.replicas|default('1') }}
placement:
constraints:
- node.role == {{ deploy_on|default('manager') }}
static:
image: hub.andrewalliance.com/releases/onelab-static:1.27.0
deploy:
replicas: 1
placement:
constraints:
- node.role == {{ deploy_on|default('manager') }}
main:
image: hub.andrewalliance.com/releases/onelab-main:1.27.0
deploy:
replicas: 1
placement:
constraints:
- node.role == {{ deploy_on|default('manager') }}
designer:
image: hub.andrewalliance.com/releases/onelab-designer:1.27.0
deploy:
replicas: 1
placement:
constraints:
- node.role == {{ deploy_on|default('manager') }}
runner:
image: hub.andrewalliance.com/releases/onelab-runner:1.27.0
deploy:
replicas: 1
placement:
constraints:
- node.role == {{ deploy_on|default('manager') }}
website:
image: hub.andrewalliance.com/releases/onelab-website:1.27.0
{% if (onelab.services.website.ssr|default(true)) != true %}
environment:
- RENDERING_MODE=no-ssr
{% endif %}
deploy:
replicas: 1
placement:
constraints:
- node.role == {{ deploy_on|default('manager') }}
revproxy:
image: hub.andrewalliance.com/releases/nginx:1.29.5-alpine
ports:
- "8080:80"
volumes:
- {{ onelab.assets.path|default('./data') }}:/data
configs:
- source: nginx.conf
target: /etc/nginx/nginx.conf
- source: error-404.html
target: /data/error-404.html
deploy:
replicas: 1
placement:
constraints:
- node.role == {{ deploy_on|default('manager') }}
volumes:
pgdata:
driver: local
rabbitmq_data:
driver: local
configs:
configurations.yml:
file: ./configurations.yml
nginx.conf:
file: ./nginx/onelab.conf
error-404.html:
file: ./proxy/error-404.html
rabbit.crt:
file: ./rabbit/ssl/rabbit.crt
rabbit.key:
file: ./rabbit/ssl/rabbit.key
rabbit.fullchain.pem:
file: ./rabbit/ssl/rabbit.fullchain.pem
enable_plugins:
file: ./rabbit/enable_plugins
rabbit.conf:
file: ./rabbit/rabbit.conf
advanced.conf:
file: ./rabbit/advanced.conf
definitions.json:
file: ./rabbit/definitions.json
{% if onelab.ldap.tls.ca is defined %}
ldap-ca.crt:
file: {{ onelab.ldap.tls.ca }}
{% endif %}
{% if onelab.ldap.tls.key is defined %}
ldap-private.key:
file: {{ onelab.ldap.tls.key }}
{% endif %}
{% if onelab.ldap.tls.cert is defined %}
ldap-cert.crt:
file: {{ onelab.ldap.tls.cert }}
{% endif %}

View File

@@ -1,337 +0,0 @@
worker_processes 4;
events { worker_connections 1024; }
http {
include /etc/nginx/mime.types;
client_max_body_size 2m;
# don't send the nginx version number in error pages and Server header
server_tokens off;
sendfile on;
upstream website {
server website:4000;
}
upstream main {
server main:80;
}
upstream api {
server api:3000;
}
upstream api-device {
server api-device:3000;
}
upstream api-rabbit {
server api-rabbit:3000;
}
upstream designer {
server designer:80;
}
upstream runner {
server runner:80;
}
upstream static {
server static:80;
}
upstream websocket-worker {
server websocket-worker:3030;
}
# Restore the real client IP from the upstream reverse proxy
# Trust all RFC 1918 private ranges (covers any Docker network config)
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16;
real_ip_header X-Real-IP;
limit_req_zone $binary_remote_addr zone=auth:10m rate=1r/s;
limit_req_zone $binary_remote_addr zone=website:10m rate=5r/s;
limit_req_zone $binary_remote_addr zone=global:10m rate=10r/s;
# redirect all http traffic to https
server {
listen 80 default_server;
{% if (onelab.services.revproxy.ipv6|default(true)) != false %}
listen [::]:80 default_server;
{% endif %}
server_name localhost;
gzip on;
gzip_vary on;
gzip_min_length 10240;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css application/json application/x-javascript application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_disable "MSIE [1-6]\.";
root /data/;
location ^~ /lab/ {
rewrite ^/lab/(.*?) /app/lab/$1 last;
}
location ^~ /assets/ {
location ~* \.(?:css|js|woff|woff2|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
expires 1M;
access_log off;
add_header Cache-Control "public";
try_files $uri $uri/ /error-404.html =404;
}
expires -1;
add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
try_files $uri $uri/ /error-404.html =404;
}
location ^~ /static/ {
location ~* \.(?:css|js|woff|woff2|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
expires 1M;
access_log off;
add_header Cache-Control "public";
proxy_pass http://static;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
expires -1;
add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
proxy_pass http://static;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
location ^~ /sitemap.xml {
limit_req zone=global burst=10 nodelay;
proxy_pass http://api;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
location ^~ /robots.txt {
limit_req zone=global burst=10 nodelay;
proxy_pass http://api;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
location ^~ /api/ {
limit_req zone=global burst=10 nodelay;
proxy_pass http://api;
proxy_redirect off;
proxy_set_header Cookie $http_cookie;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
location ^~ /api/v1/auth/ {
# apply rate limiting
limit_req zone=auth burst=5 nodelay;
proxy_pass http://api;
proxy_redirect off;
proxy_set_header Cookie $http_cookie;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
location ^~ /api/v1/firmwares {
limit_req zone=global burst=10 nodelay;
client_max_body_size 600M;
proxy_pass http://api;
proxy_redirect off;
proxy_set_header Cookie $http_cookie;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
location ^~ /api/v1/rmq/ {
proxy_pass http://api-rabbit;
proxy_redirect off;
proxy_set_header Cookie $http_cookie;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
location ^~ /device-api/ {
limit_req zone=global burst=10 nodelay;
client_max_body_size 600m;
proxy_pass http://api-device;
proxy_redirect off;
proxy_set_header Cookie $http_cookie;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
location ^~ /app/designer/ {
location ~* \.(?:css|js|woff|woff2|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
expires 1M;
access_log off;
add_header Cache-Control "public";
proxy_pass http://designer;
proxy_redirect off;
proxy_set_header Cookie $http_cookie;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
expires -1;
add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
proxy_pass http://designer;
proxy_redirect off;
proxy_set_header Cookie $http_cookie;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
location ^~ /app/runner/ {
location ~* \.(?:css|js|woff|woff2|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
expires 1M;
access_log off;
add_header Cache-Control "public";
proxy_pass http://runner;
proxy_redirect off;
proxy_set_header Cookie $http_cookie;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
expires -1;
add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
proxy_pass http://runner;
proxy_redirect off;
proxy_set_header Cookie $http_cookie;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
location ^~ /ws/ {
proxy_pass http://websocket-worker;
proxy_redirect off;
proxy_set_header Cookie $http_cookie;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location ^~ /app/ {
location ~* \.(?:css|js|woff|woff2|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
expires 1M;
access_log off;
add_header Cache-Control "public";
proxy_pass http://main;
proxy_redirect off;
proxy_set_header Cookie $http_cookie;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
expires -1;
add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
proxy_pass http://main;
proxy_redirect off;
proxy_set_header Cookie $http_cookie;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
# Static assets for website (including /media/ subdirectory)
location ~* ^/.+\.(?:css|js|woff|woff2|ttf|eot|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
expires 1M;
access_log off;
add_header Cache-Control "public";
proxy_pass http://website;
proxy_redirect off;
proxy_set_header Cookie $http_cookie;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
# Website SSR routes (rate limited)
location ~ ^/(library(/[^/]+)?|login(/(reset|change))?|signup)?$ {
limit_req zone=website burst=10 nodelay;
expires -1;
add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
proxy_pass http://website;
proxy_redirect off;
proxy_set_header Cookie $http_cookie;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
# Catch-all for junk requests
location / {
try_files $uri $uri/ /error-404.html =404;
}
}
}

View File

@@ -1,11 +0,0 @@
---
- name: Backing up OneLab (1.27.0)
hosts: localhost
gather_facts: yes
vars:
onelab_path: '../../../..'
# Call from ./installation/latest/app/playbooks/backup.yml
tasks:
- include_tasks: ./tasks/backup-task.yml

View File

@@ -1,18 +0,0 @@
---
- name: Deploying OneLab (1.27.0)
hosts: localhost
vars:
onelab_path: '../../../../../onelab'
# Call from ./installation/latest/app/playbooks/deploy.yml
tasks:
# Load configuration
- include_vars:
file: "{{ onelab_path }}/configurations.yml"
# Start proxy
- include_tasks: ./tasks/start-proxy.yml
# Start OneLab
- include_tasks: ./tasks/start-onelab.yml

View File

@@ -1,25 +0,0 @@
---
- name: Generate the command to join a node as swarm worker
hosts: localhost
gather_facts: yes
tasks:
- name: Determine Docker swarm status
shell: >
docker info | egrep 'Swarm: '
register: swarm_status
become: true
- name: Prepare the command to join a node as worker in this swarm
command: docker swarm join-token worker -q
become: true
when: "' Swarm: active' in swarm_status.stdout_lines"
register: worker_join_token
- set_fact:
run_on_worker: "sudo docker swarm join --token {{ worker_join_token.stdout }} {{ ansible_eth0.ipv4.address }}:2377"
- debug: var=run_on_worker

View File

@@ -1,13 +0,0 @@
---
- name: Installing OneLab (1.27.0)
hosts: localhost
gather_facts: yes
vars:
main_path: '../../..'
onelab_path: '../../../onelab'
installer_path: '../../../onelab-enterprise-installer-1.27.0'
# Call from ./onelab-enterprise-installer-1.27.0/app/playbooks/install.yml
tasks:
- include_tasks: ./tasks/install-task.yml

View File

@@ -1,15 +0,0 @@
---
- name: Reconfiguring OneLab (1.27.0)
hosts: localhost
vars:
main_path: '../../../../..'
onelab_path: '../../../../../onelab'
# Call from ./installation/latest/app/playbooks/reconfigure.yml
tasks:
# Load configuration
- include_vars:
file: "{{ onelab_path }}/configurations.yml"
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/reconfigure-task.yml"

View File

@@ -1,12 +0,0 @@
---
- name: Stopping OneLab (1.27.0)
hosts: localhost
vars:
onelab_path: '../../../../../onelab'
# Call from ./installation/latest/app/playbooks/stop.yml
tasks:
- include_tasks: ./tasks/stop-onelab.yml
- include_tasks: ./tasks/stop-proxy.yml

View File

@@ -1,37 +0,0 @@
---
- name: Checking if OneLab is running
shell: docker stack ls | grep 'onelab' | grep -v 'onelab_proxy' | wc -l
become: true
register: backup_stack_count
# Start DB if OneLab is not running
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/start-db-only.yml"
when: backup_stack_count.stdout == "0"
- name: Creating backup directory
file:
path: "{{ onelab_path }}/backups/{{ ansible_date_time.iso8601_basic_short }}_1.27.0"
state: directory
register: backup_path
- name: Backing up files
shell:
tar --exclude='temp' -czvf {{ backup_path.path }}/onelab.tar.gz -C {{ onelab_path }} ./data ./installation ./nginx ./proxy ./rabbit ./ssl ./backup.sh ./configurations.yml ./docker-compose.yml ./reconfigure.sh ./start.sh ./stop.sh ./update.sh
become: yes
- name: Backing up database
shell:
docker exec -i $(docker ps --filter "name=onelab_db|onelab-db" -q) pg_dump -Upostgres -Fc > {{ backup_path.path }}/db.tar.gz
become: yes
- name: Creating restore script files
copy:
src: "{{ onelab_path }}/installation/latest/resources/restore/{{ item }}"
dest: "{{ backup_path.path }}"
with_items:
- 'restore.yml'
- 'restore.sh'
# Stop DB if OneLab was not running
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/stop-db-only.yml"
when: backup_stack_count.stdout == "0"

View File

@@ -1,7 +0,0 @@
---
# Check if Docker images are existing locally
- name: Checking local Docker images bundle
stat:
path: "{{ main_path }}/onelab-images-1.27.0.tar.gz"
get_checksum: no
register: docker_images_tar

View File

@@ -1,71 +0,0 @@
---
- name: Checking internet connection
uri:
url: "https://hub.andrewalliance.com"
register: pingresult
until:
- pingresult.status == 200
retries: 3 # 3 * 5 seconds = 15s
delay: 5 # Every 5 seconds
when: (docker_images_tar is undefined) or (not docker_images_tar.stat.exists)
- name: Getting current logged-in user
shell: whoami
register: login_user
- debug: var=login_user.stdout
# User running the process may have to enter their sudo password at this step
- name: Checking if the logged-in user has sudo privileges
shell: sudo whoami
register: sudo_check
failed_when: sudo_check.stdout != "root"
- name: Checking Ansible
debug:
msg: "{{ item }}"
with_items:
- "{{ ansible_distribution }}"
- "{{ ansible_distribution_version }}"
- "{{ ansible_distribution_major_version }}"
- name: Checking Docker version
shell: docker -v | cut -d ' ' -f 3 | cut -d ',' -f 1
become: true
register: docker_version
- debug: var=docker_version.stdout
# workaround: add a dumb failed condition to avoid any failure here as the service is maybe not installed/existing
- name: Check if "docker compose" is available
shell: docker compose version
become: true
register: docker_compose_check
failed_when: "'FAILED' in docker_compose_check.stderr"
- name: Set the compose command to "docker compose"
set_fact:
compose_command: "docker compose"
when: docker_compose_check.rc == 0
- name: Fallback to "docker-compose" if "docker compose" is not available
set_fact:
compose_command: "docker-compose"
when: docker_compose_check.rc != 0
- name: Checking Docker Compose version
shell: "{{ compose_command }} version"
become: true
register: compose_version_output
- debug: var=compose_version_output.stdout
- name: Checking tar pacakge
shell: tar --usage
become: true
- name: Checking unzip pacakge
shell: unzip
become: true
- name: Checking openssl package
shell: openssl
become: true

View File

@@ -1,49 +0,0 @@
---
# Check SSL files
- name: Getting the list of Docker secrets
shell: docker secret ls | tail -n +2 | awk '{print $2}'
register: docker_secrets
become: true
- name: Checking if dhparam.pem file exists in /onelab/ssl
stat:
path: "{{ onelab_path }}/ssl/dhparam.pem"
register: dhparam
failed_when: not dhparam.stat.exists
- name: Checking if server.pem file exists in /onelab/ssl
stat:
path: "{{ onelab_path }}/ssl/server.pem"
register: serverpem
failed_when: not serverpem.stat.exists
- name: Checking if server.key file exists in /onelab/ssl
stat:
path: "{{ onelab_path }}/ssl/server.key"
register: serverkey
failed_when: not serverkey.stat.exists
- name: Checking if chain.pem file exists in /onelab/ssl
stat:
path: "{{ onelab_path }}/ssl/chain.pem"
register: chain
failed_when: not chain.stat.exists
- name: Checking if certificate and key are matching (part 1/2)
shell: >
openssl rsa -noout -modulus -in {{ onelab_path }}/ssl/server.key | openssl md5
register: serverkey_modulus
become: true
when:
- "'ssl_passphrase' not in docker_secrets.stdout_lines"
- (onelab.deployment.skip_ssl is undefined) or (onelab.deployment.skip_ssl == false)
- name: Checking if certificate and key are matching (part 2/2)
shell: >
openssl x509 -noout -modulus -in {{ onelab_path }}/ssl/server.pem | openssl md5
register: serverpem_modulus
failed_when: serverpem_modulus.stdout != serverkey_modulus.stdout
become: true
when:
- "'ssl_passphrase' not in docker_secrets.stdout_lines"
- (onelab.deployment.skip_ssl is undefined) or (onelab.deployment.skip_ssl == false)

View File

@@ -1,21 +0,0 @@
---
#
# Configure Docker
#
- name: Ensuring Docker status
service:
name: "docker"
state: started
- name: Determining Docker swarm status
shell: >
docker info | egrep 'Swarm: '
register: swarm_status
become: true
- name: Configuring Docker Swarm
shell: >
docker swarm init --advertise-addr "{{ ansible_default_ipv4.address }}"
when: "' Swarm: inactive' in swarm_status.stdout_lines"
become: true

View File

@@ -1,119 +0,0 @@
---
#
# Start Installation
#
# Folders creation
- name: Creating OneLab directory
file:
path: "{{ onelab_path }}"
state: directory
- name: Creating OneLab directory structure
file:
path: "{{ onelab_path }}/{{ item }}"
state: directory
with_items:
- 'backups'
- 'data'
- 'data/shared'
- 'data/shared/inputs'
- 'data/shared/archived'
- 'logs'
- 'installation'
- 'ssl'
- 'rabbit'
- name: Creating directory for rabbit SSL certificates
file:
path: "{{ onelab_path }}/rabbit/ssl"
state: directory
- name: Creating directory for Ansible logs
file:
path: "{{ onelab_path }}/logs/ansible"
state: directory
# Copy version
- name: Cleaning latest installation
ansible.builtin.file:
path: "{{ onelab_path }}/installation/latest"
state: absent
- name: Copying current installation bundle
ansible.builtin.copy:
src: "{{ installer_path }}/"
dest: "{{ onelab_path }}/installation/{{ item }}"
directory_mode: no
remote_src: yes
with_items:
- 'latest'
- '1.27.0'
# Copy files
- name: Copying applicative files
copy:
src: "{{ onelab_path }}/installation/latest/app/{{ item }}"
dest: "{{ onelab_path }}/"
directory_mode: yes
remote_src: yes
with_items:
- 'nginx'
- 'proxy'
- 'rabbit'
- name: Copying routine scripts
copy:
src: "{{ onelab_path }}/installation/latest/app/{{ item }}.sh"
dest: "{{ onelab_path }}/"
directory_mode: yes
remote_src: yes
with_items:
- 'start'
- 'stop'
- 'reconfigure'
- 'backup'
- 'update'
- name: Initializing custom config proxy files
file:
path: "{{ onelab_path }}/proxy/{{ item }}"
state: touch
with_items:
- 'custom-http.conf'
- 'custom-server.conf'
when: not is_update
# Initialize configurations.yml file
- name: Initializing configurations.yml file
copy:
src: "{{ onelab_path }}/installation/latest/app/configurations.yml"
dest: "{{ onelab_path }}/configurations.yml"
remote_src: yes
when: not is_update
- name: Initializing unique Password and Tokens
ansible.builtin.replace:
path: "{{ onelab_path }}/configurations.yml"
regexp: '{{ item.placeholder }}'
replace: '{{ item.value }}'
with_items:
- { placeholder: DBPasswordPlaceholder, value: '{{ lookup("password", "/dev/null length=16 chars=ascii_letters,digits") }}' }
- { placeholder: TokenAuthPlaceholder, value: '{{ lookup("password", "/dev/null length=32 chars=ascii_letters,digits") }}' }
- { placeholder: TokenRabbitPlaceholder, value: '{{ lookup("password", "/dev/null length=32 chars=ascii_letters,digits") }}' }
- { placeholder: TokenMonitoringPlaceholder, value: '{{ lookup("password", "/dev/null length=32 chars=ascii_letters,digits") }}' }
when: not is_update
- name: Initializing Rabbit SSL certificate
shell: |
openssl req -x509 -nodes -days 7300 -newkey rsa:2048 -keyout {{ onelab_path }}/rabbit/ssl/rabbit.key -out {{ onelab_path }}/rabbit/ssl/rabbit.crt -subj "/C=CH/ST=Geneva/L=Geneva/O=Andrew Alliance/OU=OneLab/CN=andrewalliance.com"
cat {{ onelab_path }}/rabbit/ssl/rabbit.crt > {{ onelab_path }}/rabbit/ssl/rabbit.fullchain.pem
become: true
when: not is_update
- name: Initializing DH Param
shell: |
openssl dhparam -out {{ onelab_path }}/ssl/dhparam.pem 2048
become: true
when: not is_update

View File

@@ -1,33 +0,0 @@
---
#
# Create onelab.service
#
- name: Check ansible-playbook bin
shell: whereis ansible-playbook | cut -d ' ' -f 2
register: ansiblebin_result
become: true
# workaround: add a dumb failed condition to avoid any failure here as the service is maybe not installed/existing
- name: Check onelab.service
shell: |
systemctl disable onelab.service
rm /etc/systemd/system/onelab.service
register: command_result
failed_when: "'FAILED' in command_result.stderr"
become: true
# playbook_dir will be /home/ubuntu/onelab/test/onelab-enterprise-installer-release-1.13.0/app/playbooks for install.sh
# but will be /home/ubuntu/onelab/test/onelab/installation/latest/app/playbooks/ for update.sh
- debug: var=playbook_dir
- name: Creating onelab.service
ansible.builtin.template:
src: "{{ installer_path }}/resources/services/onelab.service"
dest: "/etc/systemd/system/onelab.service"
become: true
- name: Configuring onelab.service
shell: |
systemctl daemon-reload
systemctl enable onelab.service
become: true

View File

@@ -1,81 +0,0 @@
---
#
# Offline-resources-check
#
- include_tasks: "{{ installer_path }}/app/playbooks/tasks/check-offline-resources.yml"
#
# Pre-check
#
- include_tasks: "{{ installer_path }}/app/playbooks/tasks/check-requirements.yml"
#
# Configure Docker
#
- include_tasks: "{{ installer_path }}/app/playbooks/tasks/init-docker.yml"
- name: Loading Docker images
debug:
msg:
- "Loading images could take few minutes, please do not interrupt"
when: (docker_images_tar is defined) and (docker_images_tar.stat.exists)
- name: Loading OneLab images from the tar file
shell:
docker load --input {{ main_path }}/onelab-images-1.27.0.tar.gz
become: true
when: (docker_images_tar is defined) and (docker_images_tar.stat.exists)
#
# Check if we are running a fresh installation or an update on an existing installation
#
- name: Checking if OneLab is already installed
stat:
path: "{{ onelab_path }}/docker-compose.yml"
register: onelab_result
#
# Pre-migration task
#
- include_tasks: "{{ installer_path }}/app/playbooks/tasks/pre-update.yml"
when: onelab_result.stat.exists
#
# Install OneLab
#
- include_tasks: "{{ installer_path }}/app/playbooks/tasks/init-onelab.yml"
vars:
is_update: "{{ onelab_result.stat.exists|bool }}"
#
# Init Service
#
- include_tasks: "{{ installer_path }}/app/playbooks/tasks/init-service.yml"
# Checking Docker volumes
- name: Checking if RabbitMQ exists
shell: docker volume ls
become: true
register: list_volumes
# Cleaning cache
- name: Cleaning RabbitMQ cache
shell: docker volume rm onelab_rabbitmq_data
become: true
when: "'onelab_rabbitmq_data' in list_volumes.stdout"
#
# Reconfigure
#
- include_vars:
file: "{{ onelab_path }}/configurations.yml"
- include_tasks: "{{ installer_path }}/app/playbooks/tasks/update-conf-files.yml"
#
# Post-migration task
#
- include_tasks: "{{ installer_path }}/app/playbooks/tasks/post-update.yml"
when: onelab_result.stat.exists

View File

@@ -1,40 +0,0 @@
- name: Connecting to Docker Hub
shell: >
docker login -u {{ onelab.docker.login.user|default('public') }} -p {{ onelab.docker.login.password|default('Andrew01..Release') }} hub.andrewalliance.com
become: true
when: (docker_images_tar is undefined) or (not docker_images_tar.stat.exists)
- name: Checking current OneLab images
shell: >
{% raw %}
docker image ls --format '{{.ID}} {{.Repository}}:{{.Tag}}' |
egrep 'onelab-' |
egrep -v '1.27.0' |
awk '{ print $1 }'
{% endraw %}
register: onelab_old_images
become: true
- name: Pruning OneLab old images
shell:
docker rmi {{ item }}
become: true
loop: "{{ onelab_old_images.stdout_lines }}"
- name: Gathering OneLab images
shell: >
cat {{ onelab_path }}/docker-compose.yml | egrep 'image: ' | awk '{ print $2 }'
register: onelab_images
become: true
when: (docker_images_tar is undefined) or (not docker_images_tar.stat.exists)
- name: Pulling OneLab images
shell: >
docker image pull {{ item }}
become: true
register: pullimages
loop: "{{ onelab_images.stdout_lines }}"
until: pullimages is not failed
retries: 10
delay: 5
when: (docker_images_tar is undefined) or (not docker_images_tar.stat.exists)

View File

@@ -1,28 +0,0 @@
---
- name: Pull new postgres image
shell: |
docker image pull hub.andrewalliance.com/releases/postgres:17.8
become: true
when: (docker_images_tar is undefined) or (not docker_images_tar.stat.exists)
- name: Cleaning database
shell: >
docker volume rm onelab_pgdata
become: true
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/start-db-only.yml"
- name: Restoring & Migrating database
shell: |
docker exec -i $(docker ps --filter "name=onelab_db|onelab-db" -q) pg_restore -Upostgres -dpostgres -v -Fc < {{ onelab_path }}/db-migration-postgres.tar.gz
rm {{ onelab_path }}/db-migration-postgres.tar.gz
become: true
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/stop-db-only.yml"
- name: Removing lock file
shell: >
rm {{ onelab_path }}/.lock_db_migration
become: true

View File

@@ -1,21 +0,0 @@
---
#
# Specfic update tasks for version
#
#
# Migrate SSL structure (1.12.0 -> 1.13.0)
#
- include_tasks: "{{ installer_path }}/app/playbooks/tasks/ssl-cert-migration.yml"
#
# Postgres13 post-migration
#
- name: Checking if database has to be migrated
stat:
path: "{{ onelab_path }}/.lock_db_migration"
register: onelab_lock_db_result
- include_tasks: "{{ installer_path }}/app/playbooks/tasks/post-db-migration.yml"
when: onelab_lock_db_result.stat.exists

View File

@@ -1,14 +0,0 @@
---
- include_tasks: "{{ installer_path }}/app/playbooks/tasks/start-db-only.yml"
- name: Backing up database
shell:
docker exec -i $(docker ps --filter "name=onelab_db|onelab-db" -q) pg_dump -Upostgres -Fc > {{ onelab_path }}/db-migration-postgres.tar.gz
become: yes
- include_tasks: "{{ installer_path }}/app/playbooks/tasks/stop-db-only.yml"
- name: Creating lock file
shell: >
touch {{ onelab_path }}/.lock_db_migration
become: true

View File

@@ -1,12 +0,0 @@
---
- name: Checking current database
shell: >
cat {{ onelab_path }}/docker-compose.yml | egrep 'image: postgres' | awk '{ print $2 }'
register: onelab_db
become: true
#
# Postgres pre-migration
#
- include_tasks: "{{ installer_path }}/app/playbooks/tasks/pre-db-migration.yml"
when: onelab_db.stdout != 'hub.andrewalliance.com/releases/postgres:17.8'

View File

@@ -1,17 +0,0 @@
---
# Evaluate Docker images bundle
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/check-offline-resources.yml"
when: (policy | default('')) != "no-pull" and (onelab.docker.policy | default('')) != "no-pull"
# Update conf files
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/update-conf-files.yml"
# Check SSL files
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/check-ssl-files.yml"
# Rotate Rabbit SSL files
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/rotate-ssl-files-for-rabbit.yml"
# Connect to Docker and pull images, and clean up old images
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/manage-images.yml"
when: (policy | default('')) != "no-pull" and (onelab.docker.policy | default('')) != "no-pull"

View File

@@ -1,8 +0,0 @@
---
# Check SSL files
- name: Rotate Rabbit SSL certificate
shell: |
openssl req -x509 -nodes -days 7300 -newkey rsa:2048 -keyout {{ onelab_path }}/rabbit/ssl/rabbit.key -out {{ onelab_path }}/rabbit/ssl/rabbit.crt -subj "/C=CH/ST=Geneva/L=Geneva/O=Andrew Alliance/OU=OneLab/CN=andrewalliance.com"
cat {{ onelab_path }}/rabbit/ssl/rabbit.crt > {{ onelab_path }}/rabbit/ssl/rabbit.fullchain.pem
become: true

View File

@@ -1,18 +0,0 @@
---
- name: Checking if fullchain.pem file exists in /onelab/ssl
stat:
path: "{{ onelab_path }}/ssl/fullchain.pem"
register: fullchain
- name: Migrating legacy SSL structure to the new one
shell: |
cp {{ onelab_path }}/ssl/fullchain.pem {{ onelab_path }}/ssl/server.pem
cp {{ onelab_path }}/ssl/fullchain.pem {{ onelab_path }}/ssl/chain.pem
rm {{ onelab_path }}/ssl/server.crt
rm {{ onelab_path }}/ssl/fullchain.pem
when: fullchain.stat.exists
register: command_result
failed_when: "'FAILED' in command_result.stderr"
become: true

View File

@@ -1,23 +0,0 @@
---
# workaround: add a dumb failed condition to avoid any failure here as the service is maybe not installed/existing
- name: Check if "docker compose" is available
shell: docker compose version
become: true
register: docker_compose_check
failed_when: "'FAILED' in docker_compose_check.stderr"
- name: Set the compose command to "docker compose"
set_fact:
compose_command: "docker compose"
when: docker_compose_check.rc == 0
- name: Fallback to "docker-compose" if "docker compose" is not available
set_fact:
compose_command: "docker-compose"
when: docker_compose_check.rc != 0
- name: Starting database service
shell: |
{{ compose_command }} -f {{ onelab_path }}/docker-compose.yml up -d db
sleep 30
become: true

View File

@@ -1,19 +0,0 @@
---
- name: Starting OneLab
shell: >
docker stack deploy onelab --compose-file {{ onelab_path }}/docker-compose.yml --with-registry-auth --prune
become: true
- name: Checking OneLab health status (could take up to 5min to be alive)
uri:
url: "{{ onelab.domain }}/api/status?token={{ onelab.security.monitoring.token }}"
return_content: yes
validate_certs: no
register: json_response
until:
- json_response.status == 200
- (json_response is defined) and (json_response.content|length > 0)
- json_response.content is search('status')
- "(json_response.content | from_json).status == 'running'"
retries: 60 # 60 * 10 seconds = 10m
delay: 10 # Every 10 seconds

View File

@@ -1,6 +0,0 @@
---
- name: Starting Proxy
shell: |
docker stack deploy onelab_proxy --compose-file {{ onelab_path }}/proxy/docker-compose.yml
sleep 10
become: true

View File

@@ -1,6 +0,0 @@
---
- name: Stopping database service
shell: |
{{ compose_command }} -f {{ onelab_path }}/docker-compose.yml down
sleep 30
become: true

View File

@@ -1,6 +0,0 @@
---
- name: Stopping OneLab
shell: |
docker stack rm onelab
sleep 30
become: true

View File

@@ -1,6 +0,0 @@
---
- name: Stopping Proxy
shell: |
docker stack rm onelab_proxy
sleep 20
become: true

View File

@@ -1,24 +0,0 @@
---
- name: Loading Docker Swarm configuration
shell: >
docker node ls | grep "Ready" | wc -l
register: nodecount
become: true
- set_fact:
deploy_on: "{{ 'manager' if (nodecount.stdout == '1') else 'worker' }}"
- name: Getting the list of Docker secrets
shell: docker secret ls | tail -n +2 | awk '{print $2}'
register: docker_secrets
become: true
- name: Reconfiguring files
ansible.builtin.template:
src: "{{ onelab_path }}/installation/latest/app/{{ item }}"
dest: "{{ onelab_path }}/{{ item }}"
with_items:
- 'docker-compose.yml'
- 'nginx/onelab.conf'
- 'proxy/proxy.conf'
- 'proxy/docker-compose.yml'

View File

@@ -1,53 +0,0 @@
---
- name: Uninstalling OneLab (1.27.0)
hosts: localhost
vars_prompt:
- name: "userchoice"
prompt: "Do you want to uninstall OneLab and remove all the data? Type: yes/no"
private: no
# Call from ./installation/latest/app/playbooks/uninstall.yml
tasks:
- name: Aborting the uninstall process
fail:
msg: Aborting the uninstall process
when: userchoice != "yes"
# Stop OneLab if OneLab is running
- name: Checking if OneLab is running
shell: docker stack ls | grep 'onelab' | wc -l
become: true
register: stack_count
- include_tasks: ./tasks/stop-onelab.yml
when: stack_count.stdout != "0"
- include_tasks: ./tasks/stop-proxy.yml
when: stack_count.stdout != "0"
# Remove Docker volumes (onelab_pgdata, onelab_rabbitmq_data)
- name: Removing Docker data
shell: |
docker volume rm onelab_pgdata -f
docker volume rm onelab_rabbitmq_data -f
become: true
# Remove Docker images
- name: Checking current OneLab images
shell: >
docker image ls | egrep 'onelab-' | egrep -v '1.27.0' | awk '{ print $3}'
register: onelab_old_images
become: true
- name: Pruning OneLab old images
shell:
docker rmi {{ item }}
become: true
loop: "{{ onelab_old_images.stdout_lines }}"
# Remove Docker login credentials
- name: Removing Docker login credentials
shell: |
docker logout hub.andrewalliance.com
become: true

View File

@@ -1,115 +0,0 @@
# This playbook updates the OneLab Enterprise to latest version or a chosen version in one step
---
- name: Updating OneLab
hosts: localhost
gather_facts: yes
vars:
main_path: '../../../../..'
onelab_path: '../../../../../onelab'
vars_prompt:
- name: "userchoice"
prompt: "Confirm OneLab update: yes/no"
private: no
tasks:
# Choice to proceed or stop the update process
- name: Aborting the update process
fail:
msg: Aborting the update process
when: userchoice != "yes"
# Gather latest version information
- name: Fetching OneLab latest version details from the repository
uri:
url: "https://hub.andrewalliance.com/enterprise/version.json"
return_content: yes
validate_certs: no
register: latest_version
become: true
when: version is undefined
- set_fact:
latest: "{{ (latest_version.content | from_json).version }}"
when: version is undefined
- name: Checking OneLab current version
fail:
msg: OneLab is already up-to-date (1.27.0)
when: (version is undefined) and (latest == "1.27.0")
- name: Starting OneLab update to {{ version | default(latest) }}
debug:
msg: Version {{ version | default(latest) }}
# Remove installer bundles if it exists already, then download & unzip
- name: Removing the bundle if it already exists
file:
state: absent
path: "{{ item }}"
with_items:
- "{{ main_path }}/onelab-enterprise-installer-{{ version | default(latest)}}"
- "{{ main_path }}/onelab-enterprise-installer-{{ version | default(latest)}}.zip"
become: true
- name: Downloading the installer bundle
shell: wget --no-check-certificate https://hub.andrewalliance.com/enterprise/onelab-enterprise-installer-{{ version | default(latest)}}.zip -P {{ main_path }}
become: true
- name: Unzip the installer bundle
shell: unzip {{ main_path }}/onelab-enterprise-installer-{{ version | default(latest)}}.zip -d {{ main_path }}/onelab-enterprise-installer-{{ version | default(latest)}}
become: true
- name: Checking if OneLab is running
shell: docker stack ls | grep 'onelab' | wc -l
become: true
register: stack_count
# Stop OneLab (unkown version) if OneLab is running
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/stop-onelab.yml"
when: stack_count.stdout != "0"
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/stop-proxy.yml"
when: stack_count.stdout != "0"
# Start Proxy (maintenance page) if OneLab was running
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/start-proxy.yml"
when: stack_count.stdout != "0"
# Perform OneLab backup
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/backup-task.yml"
# Perform OneLab update
- include_tasks: "{{ main_path }}/onelab-enterprise-installer-{{ version | default(latest)}}/app/playbooks/tasks/install-task.yml"
vars:
main_path: '../../../../..'
onelab_path: '../../../../../onelab'
installer_path: '../../../../../onelab-enterprise-installer-{{ version | default(latest)}}'
# Load configuration
- include_vars:
file: "{{ onelab_path }}/configurations.yml"
# Perform reconfiguration
# Use dynamic path (variable) to force dynamic loading of this new task
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/reconfigure-task.yml"
# Remove installer bundles
- name: Removing the installer
file:
state: absent
path: "{{ item }}"
with_items:
- "{{ main_path }}/onelab-enterprise-installer-{{ version | default(latest)}}"
- "{{ main_path }}/onelab-enterprise-installer-{{ version | default(latest)}}.zip"
become: true
# Stop Proxy (maintenance page) if OneLab was running
# Use dynamic path (variable) to force dynamic loading of this new task
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/stop-proxy.yml"
when: stack_count.stdout != "0"
# Start OneLab if OneLab was running
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/start-proxy.yml"
when: stack_count.stdout != "0"
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/start-onelab.yml"
when: stack_count.stdout != "0"

View File

@@ -1,47 +0,0 @@
version: "3.2"
services:
proxy:
image: hub.andrewalliance.com/releases/nginx:1.29.5-alpine
ports:
- target: 80
published: 80
protocol: tcp
mode: host
- target: 443
published: 443
protocol: tcp
mode: host
volumes:
- ./../ssl:/etc/nginx/ssl
- ./not-supported.html:/usr/onelab/not-supported.html
- ./error-404.html:/usr/onelab/error-404.html
- ./proxy.conf:/etc/nginx/nginx.conf
- ./custom-http.conf:/etc/nginx/custom-http.conf
- ./custom-server.conf:/etc/nginx/custom-server.conf
extra_hosts:
- "host.docker.internal:host-gateway"
deploy:
replicas: 1
placement:
constraints:
- node.role == manager
{% if docker_secrets is defined and "ssl_passphrase" in docker_secrets.stdout_lines %}
secrets:
- ssl_passphrase
{% endif %}
maintenance:
image: hub.andrewalliance.com/releases/nginx:1.29.5-alpine
volumes:
- ./maintenance.html:/usr/onelab/index.html
- ./maintenance.conf:/etc/nginx/conf.d/default.conf
deploy:
replicas: 1
placement:
constraints:
- node.role == manager
{% if docker_secrets is defined and "ssl_passphrase" in docker_secrets.stdout_lines %}
secrets:
ssl_passphrase:
external: true
{% endif %}

View File

@@ -1,98 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>OneLab - Page Not Found</title>
<meta name="description" content="The page you are looking for does not exist or has been moved.">
<meta name="robots" content="noindex, nofollow">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://fonts.googleapis.com/css?family=Open+Sans&display=swap" rel="stylesheet">
<style>
body {
font-family: "Open Sans", sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}
.page {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
text-align: center;
padding: 128px;
display: flex;
flex-direction: column;
align-items: center;
}
.content {
width: 360px;
max-width: 90%;
}
.main {
font-size: 32px;
font-weight: 600;
margin-top: 64px;
font-stretch: normal;
font-style: normal;
line-height: normal;
letter-spacing: normal;
text-align: center;
color: #4a4a4a;
}
.code {
margin-top: 8px;
font-size: 13px;
letter-spacing: 2px;
color: #888;
text-transform: uppercase;
}
.sub {
margin-top: 24px;
font-size: 15px;
line-height: 1.47;
color: #4a4a4a;
}
a.login-btn {
display: inline-block;
margin-top: 32px;
padding: 12px 28px;
border-radius: 1000px;
background: #6cb644;
color: #fff;
text-decoration: none;
font-weight: 600;
box-shadow: 0 2px 4px rgba(0, 0, 0, .15);
font-size: 15px;
}
a.login-btn:hover,
a.login-btn:focus {
background: #3a8611;
}
</style>
</head>
<body>
<div class="page" role="main" aria-labelledby="title">
<div class="content">
<div class="img">
<img
src="data:image/png;base64,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"
alt="OneLab logo">
</div>
<div class="main" id="title">Page not found</div>
<div class="code">Error 404</div>
<div class="sub">The page you requested doesnt exist, was removed, or is temporarily unavailable. You can return
to the application by logging in again.</div>
<a href="/login" class="login-btn" aria-label="Go to login page">Go to Home page</a>
</div>
</div>
</body>
</html>

View File

@@ -1,9 +0,0 @@
server {
listen 80;
location / {
root /usr/onelab;
index index.html index.htm;
try_files $uri $uri/ /index.html =404;
}
}

File diff suppressed because one or more lines are too long

View File

@@ -1,82 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>OneLab - Browser not supported</title>
<meta name="description" content="Your browser is not supported">
<meta charset="UTF-8">
<meta http-equiv="refresh" content="30">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://fonts.googleapis.com/css?family=Open+Sans&display=swap" rel="stylesheet">
<style>
body {
font-family: "Open Sans", sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}
.page {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
text-align: center;
padding: 128px;
display: flex;
flex-direction: column;
align-items: center;
}
.content {
width: 320px;
}
.main {
font-size: 32px;
font-weight: 600;
margin-top: 64px;
font-stretch: normal;
font-style: normal;
line-height: normal;
letter-spacing: normal;
text-align: center;
color: #4a4a4a;
}
.sub {
margin-top: 32px;
font-size: 15px;
font-weight: normal;
font-stretch: normal;
font-style: normal;
line-height: 1.47;
letter-spacing: normal;
text-align: center;
color: #4a4a4a;
}
</style>
</head>
<body>
<div class="page">
<div class="content">
<div class="img">
<img
src="data:image/png;base64,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"
alt="OneLab logo">
</div>
<div class="main">Your browser is not supported</div>
<div class="sub">OneLab works better on <a olLink href="https://www.google.com/chrome/">Chrome</a>, <a olLink
href="https://www.mozilla.org/en-US/firefox/new/">Firefox</a> and <a olLink
href="https://www.microsoft.com/en-us/windows/microsoft-edge">Microsoft Edge</a></div>
</div>
</div>
</body>
</html>

View File

@@ -1,174 +0,0 @@
# Load the headers-more module
load_module /etc/nginx/modules/ngx_http_headers_more_filter_module.so;
worker_processes 4;
events { worker_connections 1024; }
http {
server_names_hash_bucket_size 128;
include /etc/nginx/mime.types;
types {
image/svg+xml svg svgz;
}
client_max_body_size 600m;
# don't send the nginx version number in error pages and Server header
server_tokens off;
more_set_headers 'Server: OneLab';
sendfile on;
resolver 8.8.8.8;
limit_req_zone $binary_remote_addr zone=proxy_global:10m rate=50r/s;
upstream onelab {
server host.docker.internal:8080;
server maintenance:80 backup;
}
# redirect all http traffic to https
server {
listen 80 default_server;
{% if (onelab.services.revproxy.ipv6|default(true)) != false %}
listen [::]:80 default_server;
{% endif %}
server_name {{ onelab.domain[8:] }};
return 301 https://$host$request_uri;
}
include /etc/nginx/custom-http.conf;
server {
listen 443 ssl default_server;
{% if (onelab.services.revproxy.ipv6|default(true)) != false %}
listen [::]:443 ssl default_server;
{% endif %}
http2 on;
server_name {{ onelab.domain[8:] }};
ssl_certificate /etc/nginx/ssl/server.pem;
ssl_certificate_key /etc/nginx/ssl/server.key;
{% if docker_secrets is defined and "ssl_passphrase" in docker_secrets.stdout_lines %}
ssl_password_file /run/secrets/ssl_passphrase;
{% endif %}
# ssl_client_certificate /etc/nginx/ssl/ca.crt;
# ssl_verify_client off;
# enable session resumption to improve https performance
# http://vincent.bernat.im/en/blog/2011-ssl-session-reuse-rfc5077.html
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
# enables server-side protection from BEAST attacks
# http://blog.ivanristic.com/2013/09/is-beast-still-a-threat.html
ssl_prefer_server_ciphers on;
# disable SSLv3(enabled by default since nginx 0.8.19) since it's less secure then TLS http://en.wikipedia.org/wiki/Secure_Sockets_Layer#SSL_3.0
ssl_protocols TLSv1.2 TLSv1.3;
# ciphers chosen for forward secrecy and compatibility
# http://blog.ivanristic.com/2013/08/configuring-apache-nginx-and-openssl-for-forward-secrecy.html
ssl_ciphers 'TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_ecdh_curve X25519:P-384:P-256;
# enable ocsp stapling (mechanism by which a site can convey certificate revocation information to visitors in a privacy-preserving, scalable manner)
# http://blog.mozilla.org/security/2013/07/29/ocsp-stapling-in-firefox/
resolver 8.8.8.8 8.8.4.4;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/ssl/chain.pem;
# read more here http://tautt.com/best-nginx-configuration-for-security/
# config to enable HSTS(HTTP Strict Transport Security) https://developer.mozilla.org/en-US/docs/Security/HTTP_Strict_Transport_Security
# to avoid ssl stripping https://en.wikipedia.org/wiki/SSL_stripping#SSL_stripping
# also https://hstspreload.org/
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
# config to don't allow the browser to render the page inside an frame or iframe
# and avoid clickjacking http://en.wikipedia.org/wiki/Clickjacking
# if you need to allow [i]frames, you can use SAMEORIGIN or even set an uri with ALLOW-FROM uri
# https://developer.mozilla.org/en-US/docs/HTTP/X-Frame-Options
add_header X-Frame-Options SAMEORIGIN;
# when serving user-supplied content, include a X-Content-Type-Options: nosniff header along with the Content-Type: header,
# to disable content-type sniffing on some browsers.
# https://www.owasp.org/index.php/List_of_useful_HTTP_headers
# currently suppoorted in IE > 8 http://blogs.msdn.com/b/ie/archive/2008/09/02/ie8-security-part-vi-beta-2-update.aspx
# http://msdn.microsoft.com/en-us/library/ie/gg622941(v=vs.85).aspx
# 'soon' on Firefox https://bugzilla.mozilla.org/show_bug.cgi?id=471020
add_header X-Content-Type-Options nosniff;
# This header enables the Cross-site scripting (XSS) filter built into most recent web browsers.
# It's usually enabled by default anyway, so the role of this header is to re-enable the filter for
# this particular website if it was disabled by the user.
# https://www.owasp.org/index.php/List_of_useful_HTTP_headers
add_header X-XSS-Protection "1; mode=block";
# with Content Security Policy (CSP) enabled(and a browser that supports it(http://caniuse.com/#feat=contentsecuritypolicy),
# you can tell the browser that it can only download content from the domains you explicitly allow
# http://www.html5rocks.com/en/tutorials/security/content-security-policy/
# https://www.owasp.org/index.php/Content_Security_Policy
# I need to change our application code so we can increase security by disabling 'unsafe-inline' 'unsafe-eval'
# directives for css and js(if you have inline css or js, you will need to keep it too).
# more: http://www.html5rocks.com/en/tutorials/security/content-security-policy/#inline-code-considered-harmful
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://app.intercom.io https://widget.intercom.io https://js.intercomcdn.com https://*.google-analytics.com https://*.googletagmanager.com https://recaptcha.net https://*.recaptcha.net https://*.gstatic.com; img-src * data:; media-src *; style-src 'self' 'unsafe-inline' https://*.google-analytics.com https://*.googletagmanager.com https://recaptcha.net https://*.recaptcha.net https://*.gstatic.com; font-src 'self' https://*.intercomcdn.com https://*.google-analytics.com https://*.googletagmanager.com https://recaptcha.net https://*.recaptcha.net https://*.gstatic.com; frame-src *; connect-src 'self' https://*.intercom.io wss://*.intercom.io https://*.intercomcdn.com https://*.intercomcdn.eu https://*.intercomusercontent.com https://*.intercom-messenger.com wss://*.intercom-messenger.com https://*.google-analytics.com https://*.googletagmanager.com https://recaptcha.net https://*.recaptcha.net https://*.gstatic.com; object-src 'none'";
add_header Referrer-Policy "same-origin";
add_header Permissions-Policy "accelerometer=(), autoplay=(), camera=(), encrypted-media=(), fullscreen=(self), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), sync-xhr=(self), usb=()";
gzip on;
gzip_vary on;
gzip_min_length 10240;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css application/json application/x-javascript application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_disable "MSIE [1-6]\.";
root /usr/onelab/;
include /etc/nginx/custom-server.conf;
location /not-supported {
index not-supported.html not-supported.htm;
try_files $uri $uri/ /not-supported.html =404;
}
location /error-404 {
index error-404.html error-404.htm;
try_files $uri $uri/ /error-404.html =404;
}
# Also used as workaround for a Docker swarm issue
# https://github.com/moby/moby/issues/25526
# Redirect to HTTP, but assume that we will be on the same server
location / {
limit_req zone=proxy_global burst=50 nodelay;
if ($http_user_agent ~* '(MSIE 11.0|MSIE 10.0|MSIE 9.0|MSIE 8.0|MSIE 7.0|MSIE 6.0)') {
return 301 https://$host/not-supported;
}
proxy_pass http://onelab;
proxy_next_upstream error;
proxy_redirect off;
proxy_set_header Cookie $http_cookie;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
}

View File

@@ -1,5 +0,0 @@
[
{rabbit, [
{tcp_listeners, []}
]}
].

View File

@@ -1,20 +0,0 @@
{
"rabbit_version": "3.6.5",
"users": [
],
"vhosts": [
{
"name": "devices"
},
{
"name": "internal"
}
],
"permissions": [
],
"parameters": [],
"policies": [],
"queues": [],
"exchanges": [],
"bindings": []
}

View File

@@ -1 +0,0 @@
[rabbitmq_auth_backend_http, rabbitmq_auth_backend_cache, rabbitmq_management, rabbitmq_event_exchange].

View File

@@ -1,54 +0,0 @@
# Auth server config
auth_backends.1 = cache
auth_cache.cached_backend = http
auth_cache.cache_ttl = 5000
auth_http.user_path = http://revproxy/api/v1/rmq/user
auth_http.vhost_path = http://revproxy/api/v1/rmq/vhost
auth_http.resource_path = http://revproxy/api/v1/rmq/resource
auth_http.topic_path = http://revproxy/api/v1/rmq/topic
listeners.ssl.default = 5671
# generated with "cat server.crt server.key > server.pem"
# fullchain
ssl_options.cacertfile = /etc/rabbitmq/ssl/rabbit.fullchain.pem
ssl_options.certfile = /etc/rabbitmq/ssl/rabbit.crt
ssl_options.keyfile = /etc/rabbitmq/ssl/rabbit.key
# not very secure
ssl_options.verify = verify_peer
ssl_options.fail_if_no_peer_cert = false
# for TLS version and cipher
ssl_options.versions.1 = tlsv1.2
# these MUST be disabled if TLSv1.3 is used
ssl_options.honor_cipher_order = true
ssl_options.honor_ecc_order = true
# These are highly recommended for TLSv1.2 but cannot be used
# with TLSv1.3. If TLSv1.3 is enabled, these lines MUST be removed.
ssl_options.client_renegotiation = false
ssl_options.secure_renegotiate = true
ssl_options.ciphers.1 = ECDHE-ECDSA-AES256-GCM-SHA384
ssl_options.ciphers.2 = ECDHE-RSA-AES256-GCM-SHA384
ssl_options.ciphers.3 = ECDH-ECDSA-AES256-GCM-SHA384
ssl_options.ciphers.4 = ECDH-RSA-AES256-GCM-SHA384
ssl_options.ciphers.5 = DHE-RSA-AES256-GCM-SHA384
ssl_options.ciphers.6 = DHE-DSS-AES256-GCM-SHA384
ssl_options.ciphers.7 = ECDHE-ECDSA-AES128-GCM-SHA256
ssl_options.ciphers.8 = ECDHE-RSA-AES128-GCM-SHA256
ssl_options.ciphers.9 = ECDH-ECDSA-AES128-GCM-SHA256
ssl_options.ciphers.10 = ECDH-RSA-AES128-GCM-SHA256
ssl_options.ciphers.11 = DHE-RSA-AES128-GCM-SHA256
ssl_options.ciphers.12 = DHE-DSS-AES128-GCM-SHA256
management.load_definitions = /opt/definitions.json
# For connection events
event_exchange.vhost = devices

View File

@@ -1,23 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDwTCCAqmgAwIBAgIJANBW7LFskUGkMA0GCSqGSIb3DQEBCwUAMHcxCzAJBgNV
BAYTAkNIMQ8wDQYDVQQIDAZHZW5ldmExDzANBgNVBAcMBkdlbmV2YTEYMBYGA1UE
CgwPQW5kcmV3IEFsbGlhbmNlMQ8wDQYDVQQLDAZPbmVMYWIxGzAZBgNVBAMMEmFu
ZHJld2FsbGlhbmNlLmNvbTAeFw0xOTA5MzAxNTE5NDJaFw0zOTA5MjUxNTE5NDJa
MHcxCzAJBgNVBAYTAkNIMQ8wDQYDVQQIDAZHZW5ldmExDzANBgNVBAcMBkdlbmV2
YTEYMBYGA1UECgwPQW5kcmV3IEFsbGlhbmNlMQ8wDQYDVQQLDAZPbmVMYWIxGzAZ
BgNVBAMMEmFuZHJld2FsbGlhbmNlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAMxODu2ql2+397wUYVRjuNppa2+nLZwSvzsnyfG5RwmQX/Q3V9sy
17RluFW42WLFv5TfS/soRILbShyHmYJL9iGfsa1nkg9XAs681ebHESrGP9jZZ25x
alg97IaVI6rQcUN/7WrB183sAokL4AinY2Zh+wOt9LQWsovKO3TB3Oetxw3AImqX
onuzTZkzlbJ0KTHGpn8dZ/xjGMvkd1ByjKLQ/gb630vZOJErjcLEWji20fWhwA5S
7vhGy4dqivEpLrnEjd2njclADphOxYoHr2rN11n7ASl1+Lu5HhCAFNoeaDi+rliu
pupKcbFYCPLIpTq2yw81BOkKn0fPMn5C+m0CAwEAAaNQME4wHQYDVR0OBBYEFGYz
XZCPfN8IfCDjPVS0NUcK+c6zMB8GA1UdIwQYMBaAFGYzXZCPfN8IfCDjPVS0NUcK
+c6zMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAABxoVD1aZ8NJU2+
cL8lMFfrrQEg3vSNzYWuI78OHixGYDF3NPARFL6m20hLusxtmtsM+OsWios58RoO
0b9unY3ce0S/567LFpBZgKvo7hdEwDBY2cuX5p8snWfucn4j8KZhebtz4kvcSPOH
VTWtgfobKxcryiM8pYA8uRzu/WQKr2q92oYliiOoUg6ZQEWhBCqXzcHJ7D32UcuW
fHfZCp48D9LqfSXALNOHyXWaLXRIiQHBuWMhBI57tgbPA4m2hHN8c8y1rc0cSNGt
Og8tQoRlj9PRM3WMMrdGuG4TvBe3y5666wo1ZLErfyCbM4/sIPHdrp1cCXFDyyVj
nKZ2gjE=
-----END CERTIFICATE-----

View File

@@ -1,51 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDwTCCAqmgAwIBAgIJANBW7LFskUGkMA0GCSqGSIb3DQEBCwUAMHcxCzAJBgNV
BAYTAkNIMQ8wDQYDVQQIDAZHZW5ldmExDzANBgNVBAcMBkdlbmV2YTEYMBYGA1UE
CgwPQW5kcmV3IEFsbGlhbmNlMQ8wDQYDVQQLDAZPbmVMYWIxGzAZBgNVBAMMEmFu
ZHJld2FsbGlhbmNlLmNvbTAeFw0xOTA5MzAxNTE5NDJaFw0zOTA5MjUxNTE5NDJa
MHcxCzAJBgNVBAYTAkNIMQ8wDQYDVQQIDAZHZW5ldmExDzANBgNVBAcMBkdlbmV2
YTEYMBYGA1UECgwPQW5kcmV3IEFsbGlhbmNlMQ8wDQYDVQQLDAZPbmVMYWIxGzAZ
BgNVBAMMEmFuZHJld2FsbGlhbmNlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAMxODu2ql2+397wUYVRjuNppa2+nLZwSvzsnyfG5RwmQX/Q3V9sy
17RluFW42WLFv5TfS/soRILbShyHmYJL9iGfsa1nkg9XAs681ebHESrGP9jZZ25x
alg97IaVI6rQcUN/7WrB183sAokL4AinY2Zh+wOt9LQWsovKO3TB3Oetxw3AImqX
onuzTZkzlbJ0KTHGpn8dZ/xjGMvkd1ByjKLQ/gb630vZOJErjcLEWji20fWhwA5S
7vhGy4dqivEpLrnEjd2njclADphOxYoHr2rN11n7ASl1+Lu5HhCAFNoeaDi+rliu
pupKcbFYCPLIpTq2yw81BOkKn0fPMn5C+m0CAwEAAaNQME4wHQYDVR0OBBYEFGYz
XZCPfN8IfCDjPVS0NUcK+c6zMB8GA1UdIwQYMBaAFGYzXZCPfN8IfCDjPVS0NUcK
+c6zMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAABxoVD1aZ8NJU2+
cL8lMFfrrQEg3vSNzYWuI78OHixGYDF3NPARFL6m20hLusxtmtsM+OsWios58RoO
0b9unY3ce0S/567LFpBZgKvo7hdEwDBY2cuX5p8snWfucn4j8KZhebtz4kvcSPOH
VTWtgfobKxcryiM8pYA8uRzu/WQKr2q92oYliiOoUg6ZQEWhBCqXzcHJ7D32UcuW
fHfZCp48D9LqfSXALNOHyXWaLXRIiQHBuWMhBI57tgbPA4m2hHN8c8y1rc0cSNGt
Og8tQoRlj9PRM3WMMrdGuG4TvBe3y5666wo1ZLErfyCbM4/sIPHdrp1cCXFDyyVj
nKZ2gjE=
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDMTg7tqpdvt/e8
FGFUY7jaaWtvpy2cEr87J8nxuUcJkF/0N1fbMte0ZbhVuNlixb+U30v7KESC20oc
h5mCS/Yhn7GtZ5IPVwLOvNXmxxEqxj/Y2WducWpYPeyGlSOq0HFDf+1qwdfN7AKJ
C+AIp2NmYfsDrfS0FrKLyjt0wdznrccNwCJql6J7s02ZM5WydCkxxqZ/HWf8YxjL
5HdQcoyi0P4G+t9L2TiRK43CxFo4ttH1ocAOUu74RsuHaorxKS65xI3dp43JQA6Y
TsWKB69qzddZ+wEpdfi7uR4QgBTaHmg4vq5YrqbqSnGxWAjyyKU6tssPNQTpCp9H
zzJ+QvptAgMBAAECggEBAMNTqcAeBdSgvTBLB9bH1Ja0jSvdWKTL45qp6s+5BKqn
JqX1N4DxNftZ+Qezx9pAF288oYcJM58sCsoF9oT1HOd+pz+TMriJxrxjG9oc3lPX
4HjxOYsE0dh1s6nj8oq/6FnRd+pGU42jo7Tk7pc3ebgL2xHkgXyf6qntejShmBLC
gbXM86sPp1GYFNrVh6JveL8UBQzsXnY1u8tm4J2xA47+UvF0uPV5b7xzblplqycv
K/cijsqiaBhDZR71Nj7/HnHqcJqs4pYjnNplkfJ5fjkifJh8xZcX0vdJnc7hgC/x
BLFuMVLUSXoWtBmajVoJaD/46b0pFTEeGmXs6h3TMj0CgYEA+26WRyiyDGl3wgYJ
dm9ITuwBZQo1HiA8wGgAEqyM8BcxNh7zGhYTBKPUYJtuJsUZcFCAbXlD5nIDOYeR
bODqEgtN6RQPtQHU4My1gtd8Aaa2IlVD+GVYFSldpcud0pswbiE0xA3GcknGM3hf
Jh/7pDEYoN0DkSgyVwL5+d/irVcCgYEA0ARIZC/NyhHC17FGXF5qIG45b+pyvpAE
+ytjRHZ09WPErONnD29Q7dhNaYqi6ZtLS1XuG7GVo5VnV+xdr75e93sQuyXzAKnx
f1zn+qEDDY/K0qPeh96sHxJjwE6Ha5mO/kL7mx1yV9QEPHTNEynZMM1n2ahgv0kW
LM3vymDdN9sCgYAxCrX3NUHdV+kLCEBqQHR7KF9xRNdtg941rVNuUQfAgNWRd+H1
EZ8uBYKUQVzv5Pv8Q0d5kvCij1R/sSi1cv1U/a15q/cQWEYcfvFcjwlaDRlzguwa
FDJlFkd04k1rWefNY162avVtL2Sgf3cXqZ9cvFLQdauPcaa4ABWgHoJJSwKBgQCF
3JuxTUoC5Vcbcosy2dc1s3jm2lqo4wkxkQQ6hHhTibaBA33I4vuTc4StjHe2GSdk
/ZFS5P7E3Fo6rHLFq551aA6mQI+WN8afDWyDTqYmTghZcPa9PMBK5oymrmJbDeCF
IxnDAjoY5ukq9ocZ8+4+h5By8vX/YssQXh4XgCobzQKBgDMgav9ABc0idoE8sQ0g
bnPI/QX+bRhm+yYUQM/zB0h/CRuUC44ZP7dssST7c4L/OirYiZQEtXnHdxZ2DmV3
v/5MNbLnx+1z75KLwtg4f24BRB6p26/YxN1Wtudu7QwSSjffGRcUucbS5X3//Fjb
3YIcbL9y2FZJHQFybilFQJgu
-----END PRIVATE KEY-----

View File

@@ -1,28 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDMTg7tqpdvt/e8
FGFUY7jaaWtvpy2cEr87J8nxuUcJkF/0N1fbMte0ZbhVuNlixb+U30v7KESC20oc
h5mCS/Yhn7GtZ5IPVwLOvNXmxxEqxj/Y2WducWpYPeyGlSOq0HFDf+1qwdfN7AKJ
C+AIp2NmYfsDrfS0FrKLyjt0wdznrccNwCJql6J7s02ZM5WydCkxxqZ/HWf8YxjL
5HdQcoyi0P4G+t9L2TiRK43CxFo4ttH1ocAOUu74RsuHaorxKS65xI3dp43JQA6Y
TsWKB69qzddZ+wEpdfi7uR4QgBTaHmg4vq5YrqbqSnGxWAjyyKU6tssPNQTpCp9H
zzJ+QvptAgMBAAECggEBAMNTqcAeBdSgvTBLB9bH1Ja0jSvdWKTL45qp6s+5BKqn
JqX1N4DxNftZ+Qezx9pAF288oYcJM58sCsoF9oT1HOd+pz+TMriJxrxjG9oc3lPX
4HjxOYsE0dh1s6nj8oq/6FnRd+pGU42jo7Tk7pc3ebgL2xHkgXyf6qntejShmBLC
gbXM86sPp1GYFNrVh6JveL8UBQzsXnY1u8tm4J2xA47+UvF0uPV5b7xzblplqycv
K/cijsqiaBhDZR71Nj7/HnHqcJqs4pYjnNplkfJ5fjkifJh8xZcX0vdJnc7hgC/x
BLFuMVLUSXoWtBmajVoJaD/46b0pFTEeGmXs6h3TMj0CgYEA+26WRyiyDGl3wgYJ
dm9ITuwBZQo1HiA8wGgAEqyM8BcxNh7zGhYTBKPUYJtuJsUZcFCAbXlD5nIDOYeR
bODqEgtN6RQPtQHU4My1gtd8Aaa2IlVD+GVYFSldpcud0pswbiE0xA3GcknGM3hf
Jh/7pDEYoN0DkSgyVwL5+d/irVcCgYEA0ARIZC/NyhHC17FGXF5qIG45b+pyvpAE
+ytjRHZ09WPErONnD29Q7dhNaYqi6ZtLS1XuG7GVo5VnV+xdr75e93sQuyXzAKnx
f1zn+qEDDY/K0qPeh96sHxJjwE6Ha5mO/kL7mx1yV9QEPHTNEynZMM1n2ahgv0kW
LM3vymDdN9sCgYAxCrX3NUHdV+kLCEBqQHR7KF9xRNdtg941rVNuUQfAgNWRd+H1
EZ8uBYKUQVzv5Pv8Q0d5kvCij1R/sSi1cv1U/a15q/cQWEYcfvFcjwlaDRlzguwa
FDJlFkd04k1rWefNY162avVtL2Sgf3cXqZ9cvFLQdauPcaa4ABWgHoJJSwKBgQCF
3JuxTUoC5Vcbcosy2dc1s3jm2lqo4wkxkQQ6hHhTibaBA33I4vuTc4StjHe2GSdk
/ZFS5P7E3Fo6rHLFq551aA6mQI+WN8afDWyDTqYmTghZcPa9PMBK5oymrmJbDeCF
IxnDAjoY5ukq9ocZ8+4+h5By8vX/YssQXh4XgCobzQKBgDMgav9ABc0idoE8sQ0g
bnPI/QX+bRhm+yYUQM/zB0h/CRuUC44ZP7dssST7c4L/OirYiZQEtXnHdxZ2DmV3
v/5MNbLnx+1z75KLwtg4f24BRB6p26/YxN1Wtudu7QwSSjffGRcUucbS5X3//Fjb
3YIcbL9y2FZJHQFybilFQJgu
-----END PRIVATE KEY-----

View File

@@ -1,21 +0,0 @@
#!/bin/bash
# Usage: ./reconfigure.sh [--no-pull]
onelab_no_pull=""
for arg in "$@"; do
if [[ "$arg" == "--no-pull" ]]; then
onelab_no_pull="no-pull"
fi
done
LOG_PATH="./logs/ansible/$(date +%F)-ansible.log"
PLAYBOOK="./installation/1.27.0/app/playbooks/reconfigure.yml"
EXTRA_VARS=()
if [[ -n "$onelab_no_pull" ]]; then
EXTRA_VARS+=("-e" "policy=$onelab_no_pull")
fi
ANSIBLE_LOG_PATH="$LOG_PATH" ansible-playbook "$PLAYBOOK" "${EXTRA_VARS[@]}"

View File

@@ -1,3 +0,0 @@
#!/bin/bash
ANSIBLE_LOG_PATH=./logs/ansible/$(date +%F)-ansible.log ansible-playbook ./installation/latest/app/playbooks/deploy.yml

View File

@@ -1,3 +0,0 @@
#!/bin/bash
ANSIBLE_LOG_PATH=./logs/ansible/$(date +%F)-ansible.log ansible-playbook ./installation/latest/app/playbooks/stop.yml

View File

@@ -1,2 +0,0 @@
#!/bin/bash
ansible-playbook ./installation/1.27.0/app/playbooks/uninstall.yml

View File

@@ -1,26 +0,0 @@
#!/bin/bash
# Usage: ./update.sh [version] [--force]
onelab_version=""
onelab_force_update=""
for arg in "$@"; do
if [[ "$arg" == "--force" ]]; then
onelab_force_update="--force"
else
onelab_version="$arg"
fi
done
LOG_PATH="./logs/ansible/$(date +%F)-ansible.log"
PLAYBOOK="./installation/1.27.0/app/playbooks/update.yml"
EXTRA_VARS=()
if [[ -n "$onelab_version" ]]; then
EXTRA_VARS+=("-e" "version=$onelab_version")
fi
if [[ -n "$onelab_force_update" ]]; then
EXTRA_VARS+=("-e" "userchoice=yes")
fi
ANSIBLE_LOG_PATH="$LOG_PATH" ansible-playbook "$PLAYBOOK" "${EXTRA_VARS[@]}"

View File

@@ -1,33 +1,89 @@
# OneLab GitOps (Argo CD) # OneLab GitOps (Argo CD)
This directory is the **declarative source** for OneLab on Kubernetes. Argo CD applies two **Helm-based sources** from Git (Argo invokes Helm internally; you do not run a separate Helm install workflow). This directory is the **declarative source** for OneLab on Kubernetes. [Argo CD](https://argo-cd.readthedocs.io/) applies **two Helm-based sources** from Git (Argo invokes Helm; you do not use Helm CLI as the primary install path for the cluster).
Legacy Swarm install lives under [`app/`](../app/) (`docker-compose.yml`); this tree replaces `docker stack deploy` for k3s/Kubernetes. This repository is **GitOps-only**: everything required to deploy OneLab on Kubernetes lives under **`gitops/`**.
## What gets deployed
| Helm release | Chart path | Namespace | Role |
|--------------|------------|-----------|------|
| `onelab` | [`charts/onelab`](charts/onelab) | `onelab` | Application workloads, Postgres, Redis, RabbitMQ, revproxy, ingress hooks |
| `onelab-obs` | [`observability/`](observability/) | `onelab` | Loki, Promtail, Grafana (logs) |
Both are wired by a single Argo CD [`Application`](argocd/application.yaml) using **`spec.sources`** (requires **Argo CD 2.6+**).
## Architecture
```mermaid
flowchart LR
subgraph git [Git repository]
V[gitops/values]
C[charts/onelab]
O[observability]
end
subgraph argo [Argo CD]
App[Application onelab]
end
subgraph cluster [Kubernetes cluster]
NS[namespace onelab]
end
V --> App
C --> App
O --> App
App --> NS
```
1. You commit changes under **`gitops/values/`** (and optionally edit `repoURL` / `targetRevision` in the Application).
2. Argo reconciles: Helm renders `onelab` + `onelab-obs` into namespace **`onelab`**.
3. Sync waves order StatefulSets and app Deployments (Postgres → Redis/Rabbit/config → apps).
## Layout ## Layout
| Path | Purpose | | Path | Purpose |
|------|---------| |------|---------|
| [`charts/onelab`](charts/onelab) | OneLab chart (StatefulSets, Deployments, Services, ConfigMaps, Secrets)**Argo source 1** | | [`charts/onelab`](charts/onelab) | OneLab Helm chart — **Argo source 1** |
| [`values/`](values/) | Environment values (e.g. [`values/k3s-example.yaml`](values/k3s-example.yaml)); reference from `helm.valueFiles` | | [`values/`](values/) | **Operator entry point**: [`values/env-example.yaml`](values/env-example.yaml), [`values/observability.yaml`](values/observability.yaml), templates — see [`values/README.md`](values/README.md) |
| [`observability/`](observability/) | Loki / Promtail / Grafana umbrella chart — **Argo source 2** (`releaseName: onelab-obs`) | | [`observability/`](observability/) | Loki / Promtail / Grafana umbrella chart — **Argo source 2** (`releaseName: onelab-obs`) |
| [`argocd/application.yaml`](argocd/application.yaml) | `Application` manifest (`spec.sources`, namespace `onelab`) | | [`argocd/application.yaml`](argocd/application.yaml) | `Application` manifest (`spec.sources`, destination namespace `onelab`) |
| [`argocd/jsonpatch-multisource.json`](argocd/jsonpatch-multisource.json) | One-time JSON patch if the live `Application` stuck on `spec.source` | | [`argocd/jsonpatch-multisource.json`](argocd/jsonpatch-multisource.json) | One-time JSON patch if a live `Application` still has legacy `spec.source` only |
## Prerequisites ## Prerequisites
1. **Kubernetes** (e.g. k3s) with a default **StorageClass** for Postgres/Rabbit PVCs (e.g. `local-path`). 1. **Kubernetes** (e.g. k3s) with a default **StorageClass** for Postgres/Rabbit/Loki/Grafana PVCs (e.g. `local-path`).
2. **Image pull** to `hub.andrewalliance.com` registry Secret + `imagePullSecrets` (see [`values/k3s-example.yaml`](values/k3s-example.yaml) and [Private registry credentials](#private-registry-credentials)). 2. **Container images** from `hub.andrewalliance.com` (or your mirror): registry credentials via Helm values or a pre-created `docker-registry` Secret — see [Private registry credentials](#private-registry-credentials).
3. **RabbitMQ TLS** Secret `onelab-rabbit-tls` (or `rabbitmq.tls.embed` in a private values file) — [RabbitMQ TLS](#rabbitmq-tls). 3. **RabbitMQ TLS** before RabbitMQ starts: Kubernetes Secret `onelab-rabbit-tls`, or `rabbitmq.tls.embed` in private values — see [RabbitMQ TLS](#rabbitmq-tls).
4. **Host paths** when using `persistence.mode: hostPath`: `/opt/onelab/data` and `/opt/onelab/logs` on nodes that run those pods, or use RWX storage for multi-node. 4. **Host paths** when using `persistence.mode: hostPath`: `/opt/onelab/data` and `/opt/onelab/logs` on nodes that run those pods (aligned with Promtail in [`values/observability.yaml`](values/observability.yaml)), or use RWX storage for multi-node.
## Bootstrap (registry, Argo repo, TLS) ## Configuration (single place to edit)
### Private registry credentials - **OneLab app / ingress / DB / tokens / registry**: [`values/env-example.yaml`](values/env-example.yaml) — copy patterns, replace **`REPLACE_*`** placeholders, or overlay a gitignored file; see [`values/secrets.example.yaml`](values/secrets.example.yaml) and [`values/README.md`](values/README.md).
- **Observability**: [`values/observability.yaml`](values/observability.yaml) — Grafana password (**`REPLACE_GRAFANA_ADMIN_PASSWORD`**), ingress host, Promtail log hostPath.
- **Argo Git coordinates**: [`argocd/application.yaml`](argocd/application.yaml) — set `repoURL`, `targetRevision`, and `helm.valueFiles` if you add e.g. `secrets.local.yaml`.
By default, `gitops/values/k3s-example.yaml` matches the Swarm installer (`app/playbooks/tasks/manage-images.yml`): user **`public`**, password **`Andrew01..Release`**, and the chart creates Secret **`hub-andrewalliance`** when `registry.createPullSecret: true`. The chart default [`charts/onelab/values.yaml`](charts/onelab/values.yaml) holds non-secret structure and safe placeholders only; **do not rely on it for production secrets**.
To use other credentials, override `registry.username` / `registry.password` or create the secret manually: ## Bootstrap checklist
1. Fork or clone this repository and push it to a Git remote your cluster can reach.
2. Edit [`argocd/application.yaml`](argocd/application.yaml): **`repoURL`** → your remote, **`targetRevision`** → your branch/tag.
3. Edit [`values/env-example.yaml`](values/env-example.yaml): DNS hostnames, TLS secret names, cert-manager issuer, and all **`REPLACE_*`** values (or use a gitignored overlay).
4. Edit [`values/observability.yaml`](values/observability.yaml): Grafana host/password aligned with your DNS and TLS.
5. If the Git repo is **private**, register it in Argo CD (see below).
6. Ensure **RabbitMQ TLS** Secret exists (or use embedded TLS in private values).
7. Apply the Application:
```bash
kubectl apply -f gitops/argocd/application.yaml
```
8. In Argo UI or CLI, confirm sync to namespace **`onelab`** and fix any `ImagePullBackOff` / TLS issues using the sections below.
**Single controller:** Use **only** this Argo CD `Application` for `onelab` / `onelab-obs`. Do not manage the same namespace with a parallel **Helm CLI** release.
## Private registry credentials
Set `registry.username` / `registry.password` in values (prefer a **gitignored** file merged last), or create the Secret manually:
```bash ```bash
kubectl create secret docker-registry hub-andrewalliance -n onelab \ kubectl create secret docker-registry hub-andrewalliance -n onelab \
@@ -36,72 +92,50 @@ kubectl create secret docker-registry hub-andrewalliance -n onelab \
--docker-password='YOUR_PASSWORD' --docker-password='YOUR_PASSWORD'
``` ```
…and set `registry.createPullSecret: false` plus `imagePullSecrets: [{ name: hub-andrewalliance }]`. …then set `registry.createPullSecret: false` and keep `imagePullSecrets: [{ name: hub-andrewalliance }]` in values.
#### StatefulSet pods still get `401 Unauthorized` / `ImagePullBackOff` after enabling registry auth ### StatefulSet pods still get `401 Unauthorized` / `ImagePullBackOff` after enabling registry auth
If `db-0` / `rabbitmq-0` were created **before** `imagePullSecrets` existed, their **Pod** spec can still use anonymous pulls until they are recreated: If `db-0` / `rabbitmq-0` were created **before** `imagePullSecrets` existed, delete those pods once so they pick up the new Pod spec:
```bash ```bash
kubectl delete pod -n onelab db-0 rabbitmq-0 kubectl delete pod -n onelab db-0 rabbitmq-0
``` ```
The chart adds a pod-template checksum so after you change registry settings in Git and **Argo syncs**, workloads normally roll; a one-time delete is enough if pods were created before pull secrets existed. ## Argo CD private Git repository
### Argo CD private Git repository If the Application shows `authentication required: Unauthorized`, register the repo (use a deploy token or PAT with read access):
If the Application shows `authentication required: Unauthorized`, register the repo in Argo CD (CLI or UI):
```bash ```bash
# Example; use a deploy token or PAT with repo read access argocd repo add https://github.com/YOUR_ORG/YOUR_REPO.git \
argocd repo add https://git.luneski.fr/luneski/onelab-k8s.git \
--username git \ --username git \
--password YOUR_TOKEN --password YOUR_TOKEN
``` ```
Then apply the Application: ## RabbitMQ TLS
Secret **`onelab-rabbit-tls`** must exist in namespace **`onelab`** before RabbitMQ starts (keys: typically `tls.crt`, `tls.key`, and optionally chain). **PEM material is not shipped in this GitOps tree** — generate certs or use your PKI, then:
```bash ```bash
kubectl apply -f gitops/argocd/application.yaml kubectl create secret tls onelab-rabbit-tls -n onelab \
--cert=path/to/fullchain.pem \
--key=path/to/key.pem
``` ```
**Single controller:** Use **only** this Argo CD `Application` for `onelab` / `onelab-obs`. Do not manage the same namespace with a separate **Helm CLI** release. Alternatively, set `rabbitmq.tls.embed: true` and supply `rabbitmq.tls.crt` / `rabbitmq.tls.key` / `rabbitmq.tls.fullchain` via a **private** values file (never commit real keys).
### RabbitMQ TLS ## Deploy with Argo CD (details)
Secret `onelab-rabbit-tls` must exist before RabbitMQ starts (created once from `app/rabbit/ssl/` or your own PEMs).
### Argo CD version and observability stack
[`argocd/application.yaml`](argocd/application.yaml) uses **`spec.sources`** (two Helm charts in one Application). Use **Argo CD 2.6 or newer**.
If the `onelab` Application was created earlier with **`spec.source` only**, Argo will **not** show the observability resources until you remove `source` and set `sources` — see [Migrating `spec.source` → `spec.sources`](#migrating-specsource--specsources) below.
The second source installs Loki/Promtail/Grafana from [`observability/`](observability/) (`releaseName: onelab-obs`). Set a strong **`grafana.adminPassword`** in [`observability/values.yaml`](observability/values.yaml) before production — details in [Observability](#observability-loki--promtail--grafana).
## Deploy with Argo CD
1. Push this repo to a Git remote Argo CD can read.
2. Register the repo in Argo CD (CLI or UI) if it is private — [Argo CD private Git repository](#argo-cd-private-git-repository).
3. Edit [`argocd/application.yaml`](argocd/application.yaml): `repoURL`, `targetRevision`, and per-source `helm.valueFiles` if needed.
4. Apply the Application:
```bash
kubectl apply -f gitops/argocd/application.yaml
```
**Requirements:** Argo CD **2.6+** (`spec.sources`). **Requirements:** Argo CD **2.6+** (`spec.sources`).
Each entry under `spec.sources` has its own `helm.releaseName` and `helm.valueFiles` (paths are **relative to that sources `path`**): Each entry under `spec.sources` has its own `helm.releaseName` and `helm.valueFiles` (paths are **relative to that sources `path`**):
- Source `gitops/charts/onelab` → e.g. `../../values/k3s-example.yaml` - Source `gitops/charts/onelab` → e.g. `../../values/env-example.yaml`, optionally `../../values/secrets.local.yaml`
- Source `gitops/observability` → e.g. `values.yaml` - Source `gitops/observability` → e.g. `../../values/observability.yaml`
Both targets deploy into namespace **`onelab`**. Sync waves order: Postgres → Redis/Rabbit/config → application workloads.
### Migrating `spec.source` → `spec.sources` ### Migrating `spec.source` → `spec.sources`
If the `onelab` `Application` was created earlier with **`spec.source` only**, a plain `kubectl apply` of the new file may **not** remove `spec.source`, and Argo will never reconcile the observability chart. If the `onelab` `Application` was created earlier with **`spec.source` only**, a plain `kubectl apply` may **not** remove `spec.source`, and Argo will not reconcile the observability chart.
Check: Check:
@@ -109,66 +143,41 @@ Check:
kubectl get application onelab -n argocd -o jsonpath='{.spec.source}{"\n"}{.spec.sources}{"\n"}' kubectl get application onelab -n argocd -o jsonpath='{.spec.source}{"\n"}{.spec.sources}{"\n"}'
``` ```
If `source` is set and `sources` is empty, patch once (adjust `repoURL` in the patch file if needed): If `source` is set and `sources` is empty, patch once (edit `repoURL` in the patch file to match your remote):
```bash ```bash
kubectl patch application onelab -n argocd --type json --patch-file gitops/argocd/jsonpatch-multisource.json kubectl patch application onelab -n argocd --type json --patch-file gitops/argocd/jsonpatch-multisource.json
``` ```
Then sync in Argo (or wait for auto-sync).
### Single controller
Manage these workloads **only** through this Argo CD `Application`. Do not drive the same resources with a parallel **Helm CLI** release.
### Logs / Grafana
See [Observability (Loki / Promtail / Grafana)](#observability-loki--promtail--grafana) — set a strong `grafana.adminPassword` in [`observability/values.yaml`](observability/values.yaml) before production.
## Observability (Loki / Promtail / Grafana) ## Observability (Loki / Promtail / Grafana)
The umbrella chart under [`observability/`](observability/) deploys: The umbrella chart under [`observability/`](observability/) deploys:
- **Loki** — log storage (SingleBinary, filesystem PVC, 7-day retention by default). - **Loki** — log storage (SingleBinary, filesystem PVC; retention from [`values/observability.yaml`](values/observability.yaml)).
- **Promtail** — DaemonSet: Kubernetes pod logs (`/var/log/pods`) plus **OneLab file logs** from the same host path the app chart uses (`/opt/onelab/logs` by default). - **Promtail** — DaemonSet: Kubernetes pod logs plus **OneLab file logs** from the host path configured in [`values/observability.yaml`](values/observability.yaml) (keep in sync with OneLab `persistence.hostPath.logs`).
- **Grafana** — explore logs; datasource points at this releases Loki gateway. - **Grafana** — Explore; datasource points at this releases Loki gateway.
It is synced by the **same** Argo CD Application as the OneLab chart ([`argocd/application.yaml`](argocd/application.yaml)): second `sources` entry, Argo **`helm.releaseName`** **`onelab-obs`** (so services are like `onelab-obs-loki-gateway`).
### First-time setup ### First-time setup
1. **Change the Grafana admin password** in [`observability/values.yaml`](observability/values.yaml) (`grafana.adminPassword`) or switch to `admin.existingSecret` per the upstream Grafana chart. 1. Set a strong **`grafana.adminPassword`** in [`values/observability.yaml`](values/observability.yaml) (or use `admin.existingSecret` per the upstream Grafana chart).
2. **Align host paths** — if you change `persistence.hostPath.logs` for OneLab, update `promtail.extraVolumes` / `extraVolumeMounts` in the same `values.yaml` so Promtail still reads the shared log directory. 2. Align **Grafana ingress host** with `grafana.ini.server.domain` / `root_url` in the same file.
3. **Multi-node** — with `hostPath` logs, each node only sees its own files; Promtail runs on every node, so you still get coverage when pods move. 3. **Multi-node** — with `hostPath` logs, each node only sees its own files; Promtail runs on every node.
### OneLab-only ingestion ### OneLab-only ingestion
Promtail adds **`extraRelabelConfigs`** so the **kubernetes-pods** job **keeps only** pods in namespace **`onelab`**. Other namespaces no longer reach Loki (Explore only sees OneLab). Host file logs under `/opt/onelab/logs` are tagged with **`namespace: onelab`** and **`component: host-logs`** so they appear in the same queries. Promtail **`extraRelabelConfigs`** keep only pods in namespace **`onelab`**. Host file logs are tagged **`namespace: onelab`**, **`component: host-logs`**.
Existing Loki data from before this change may still show non-`onelab` streams until **retention** drops them; for a clean index you would need to wipe the Loki PVC (destructive).
### Dashboard: **OneLab logs** ### Dashboard: **OneLab logs**
Grafanas **dashboard sidecar** loads ConfigMap **`…-dashboard-onelab-logs`** (JSON: `observability/dashboards/onelab-logs.json`). Open **Dashboards → OneLab logs** (`uid` `onelab-logs`): Grafana sidecar loads the dashboard from `observability/dashboards/onelab-logs.json` (`uid` `onelab-logs`).
- **Component** — multi-select from `label_values({namespace="onelab"}, component)` (includes **`host-logs`** for file logs).
- **Line filter** — regex applied to log line content (`.*` = all).
- Stat panels: total lines, heuristic **error** / **warning** counts (tuned for typical text logs, not strict JSON parsing).
#### Grafana pod: `init-chown-data` CrashLoopBackOff #### Grafana pod: `init-chown-data` CrashLoopBackOff
The upstream chart runs an init container as **root** to `chown` `/var/lib/grafana`. Clusters with **Pod Security Admission** (often on k3s) commonly block that. This repo sets **`grafana.initChownData.enabled: false`**; the Grafana pod keeps **`fsGroup: 472`** so the PVC is usually group-writable. If Grafana still cannot write to disk, delete the Grafana PVC once after the change or relax PSA for namespace `onelab`. This repo sets **`grafana.initChownData.enabled: false`** with **`fsGroup: 472`** for Pod Securityfriendly clusters. If Grafana cannot write to the PVC, delete the Grafana PVC once after changing values or adjust Pod Security for namespace `onelab`.
### Access Grafana ### Access Grafana
An **Ingress** named **`grafana-onelab`** is created by the umbrella chart (`observability/templates/ingress-grafana-onelab.yaml`), Traefik + cert-manager, matching the OneLab web UI pattern in `gitops/values/k3s-example.yaml`: Ingress **`grafana-onelab`** is defined in `observability/templates/ingress-grafana-onelab.yaml`. Defaults use example hosts in [`values/observability.yaml`](values/observability.yaml) (`grafana.onelab.example.com`); change to your DNS and TLS Secret name.
- Host: **`grafana.k8s.selair.it`** — edit `grafanaOnelabIngress` and `grafana.ini.server` in `gitops/observability/values.yaml` together.
- TLS Secret: **`grafana-tls-k8s-selair`** (cert-manager with `letsencrypt-prod`).
Point DNS at your ingress, sync the app, then open `https://<grafana-host>/` (user `admin` until you change values).
For debugging without DNS:
```bash ```bash
kubectl -n onelab port-forward svc/onelab-obs-grafana 3000:80 kubectl -n onelab port-forward svc/onelab-obs-grafana 3000:80
@@ -176,42 +185,39 @@ kubectl -n onelab port-forward svc/onelab-obs-grafana 3000:80
### Maintainers: vendored chart dependencies ### Maintainers: vendored chart dependencies
The observability umbrella vendors upstream charts under `gitops/observability/charts/*.tgz` so **Argo CD** can render without relying on live Helm repo access at sync time. From `gitops/observability/`:
When bumping Loki / Promtail / Grafana versions, from `gitops/observability/` run:
```bash ```bash
helm dependency update helm dependency update
``` ```
Commit the updated `Chart.lock` and `charts/*.tgz` with your Git change. This is **repository packaging**, not an alternative install path — deploy still happens only via Argo CD. Commit updated `Chart.lock` and `charts/*.tgz` so Argo can render without live Helm repo access at sync time.
### OneLab `logs.path`
The OneLab chart sets `onelab.logs.path: "/logs"` in the generated configuration so application file logs match the `/logs` volume mount (see Enterprise guide §7.2).
## kubectl / credentials
If `kubectl` reports *You must be logged in*, refresh your kubeconfig (e.g. k3s `/etc/rancher/k3s/k3s.yaml` on the server or your auth plugin) before applying manifests.
## Application configuration (`configurations.yml`) ## Application configuration (`configurations.yml`)
You do not need to edit [`app/configurations.yml`](../app/configurations.yml) in Git for Kubernetes. The chart renders `configurations.yml` from [`charts/onelab/files/configurations.gotmpl`](charts/onelab/files/configurations.gotmpl) into Secret **`onelab-configurations`**. For Kubernetes you do **not** need a separate `configurations.yml` in Git. The OneLab chart renders it from [`charts/onelab/files/configurations.gotmpl`](charts/onelab/files/configurations.gotmpl) into Secret **`onelab-configurations`**.
1. **Values (recommended)** — set `onelab.compliance`, `onelab.ldap`, etc. See [`values/instance-overrides.example.yaml`](values/instance-overrides.example.yaml). Add extra paths under **`spec.sources[].helm.valueFiles`** for the `gitops/charts/onelab` source (paths relative to `gitops/charts/onelab`). 1. **Values (recommended)** — set `onelab.compliance`, `onelab.ldap`, etc. See [`values/instance-overrides.example.yaml`](values/instance-overrides.example.yaml) and add paths under **`spec.sources[].helm.valueFiles`** for the `gitops/charts/onelab` source.
2. **Bring your own Secret** — set `configuration.existingSecretName`; the Secret must contain key **`configurations.yml`**. 2. **Bring your own Secret** — set `configuration.existingSecretName`; the Secret must contain key **`configurations.yml`**.
LDAP TLS paths in values are container paths; mount PEMs on `ldap-worker` if required.
## Ingress (web UI) ## Ingress (web UI)
Set `ingress.enabled`, `ingress.host`, and optional TLS in values. Traffic goes to Service **`revproxy`**. On k3s, `ingress.className: traefik` matches the default controller. For cert-manager, set `ingress.tls`, `ingress.tlsSecretName`, and `ingress.certManager.clusterIssuer`; DNS for `ingress.host` must resolve before ACME runs. Set `ingress.enabled`, `ingress.host`, and optional TLS in [`values/env-example.yaml`](values/env-example.yaml). Traffic goes to Service **`revproxy`**. On k3s, `ingress.className: traefik` matches the default controller. For cert-manager, set `ingress.certManager.clusterIssuer` and TLS secret name; DNS for `ingress.host` must resolve before ACME completes.
## Security notes for public repositories
- Never commit real passwords, tokens, or TLS private keys. Use **`REPLACE_*`** in tracked files and a **`*.local.yaml`** overlay (ignored at repo root) for secrets.
- If this repo ever contained real credentials, **rotate** them after sanitizing Git history or publishing a clean fork.
## kubectl / credentials
If `kubectl` reports *You must be logged in*, refresh your kubeconfig before applying manifests.
## Developer note (local render) ## Developer note (local render)
Running **`helm template` on Windows** against some paths can return empty `.Files.Get` content; the OneLab chart uses `fromYaml (.Files.AsConfig)` where needed. **Argo CD runs on Linux** and renders the same charts in-cluster — this is a local-tooling caveat, not a second deploy path. Running **`helm template` on Windows** against some paths can return empty `.Files.Get` content; the OneLab chart uses `fromYaml (.Files.AsConfig)` where needed. **Argo CD runs on Linux** and renders the same charts in-cluster.
## Not migrated in this chart ## Not covered by this chart
- **Edge proxy stack** (`app/proxy/docker-compose.yml`, host 80/443 Swarm) — use **Ingress** + `revproxy` and optional cert-manager. - **Edge proxy** in front of the cluster — use **Ingress** + `revproxy` and optional cert-manager.
- **Swarm-only secrets** (e.g. `ssl_passphrase`) — use Kubernetes Secrets or external operators. - **Non-Kubernetes** install paths — not included; use Kubernetes Secrets or external secret operators as needed.

View File

@@ -13,20 +13,20 @@ metadata:
spec: spec:
project: default project: default
sources: sources:
- repoURL: https://git.luneski.fr/luneski/onelab-k8s.git - repoURL: https://github.com/YOUR_ORG/YOUR_REPO.git
targetRevision: main targetRevision: main
path: gitops/charts/onelab path: gitops/charts/onelab
helm: helm:
releaseName: onelab releaseName: onelab
valueFiles: valueFiles:
- ../../values/k3s-example.yaml - ../../values/env-example.yaml
- repoURL: https://git.luneski.fr/luneski/onelab-k8s.git - repoURL: https://github.com/YOUR_ORG/YOUR_REPO.git
targetRevision: main targetRevision: main
path: gitops/observability path: gitops/observability
helm: helm:
releaseName: onelab-obs releaseName: onelab-obs
valueFiles: valueFiles:
- values.yaml - ../../values/observability.yaml
destination: destination:
server: https://kubernetes.default.svc server: https://kubernetes.default.svc
namespace: onelab namespace: onelab

View File

@@ -2,21 +2,21 @@
{"op": "remove", "path": "/spec/source"}, {"op": "remove", "path": "/spec/source"},
{"op": "add", "path": "/spec/sources", "value": [ {"op": "add", "path": "/spec/sources", "value": [
{ {
"repoURL": "https://git.luneski.fr/luneski/onelab-k8s.git", "repoURL": "https://github.com/YOUR_ORG/YOUR_REPO.git",
"targetRevision": "main", "targetRevision": "main",
"path": "gitops/charts/onelab", "path": "gitops/charts/onelab",
"helm": { "helm": {
"releaseName": "onelab", "releaseName": "onelab",
"valueFiles": ["../../values/k3s-example.yaml"] "valueFiles": ["../../values/env-example.yaml"]
} }
}, },
{ {
"repoURL": "https://git.luneski.fr/luneski/onelab-k8s.git", "repoURL": "https://github.com/YOUR_ORG/YOUR_REPO.git",
"targetRevision": "main", "targetRevision": "main",
"path": "gitops/observability", "path": "gitops/observability",
"helm": { "helm": {
"releaseName": "onelab-obs", "releaseName": "onelab-obs",
"valueFiles": ["values.yaml"] "valueFiles": ["../../values/observability.yaml"]
} }
} }
]} ]}

View File

@@ -23,13 +23,13 @@ images:
imagePullSecrets: [] imagePullSecrets: []
# - name: hub-andrewalliance # - name: hub-andrewalliance
# Same defaults as app/playbooks/tasks/manage-images.yml (docker login before pull). # Override registry credentials in gitops/values/ (see gitops/values/secrets.example.yaml).
registry: registry:
createPullSecret: false createPullSecret: false
pullSecretName: hub-andrewalliance pullSecretName: hub-andrewalliance
server: hub.andrewalliance.com server: hub.andrewalliance.com
username: public username: public
password: Andrew01..Release password: "REPLACE_REGISTRY_PASSWORD"
# hostPath: matches typical single-node Swarm-style install (shared /data and /logs). # hostPath: matches typical single-node Swarm-style install (shared /data and /logs).
# Use persistence.mode: pvc + a ReadWriteMany class for multi-node shared storage. # Use persistence.mode: pvc + a ReadWriteMany class for multi-node shared storage.
@@ -71,12 +71,12 @@ syncWaves:
onelab: onelab:
domain: "https://localhost" domain: "https://localhost"
mailer: mailer:
noreply: "no-reply@andrewalliance.com" noreply: "no-reply@example.com"
secrets: secrets:
authTokenKey: "TokenAuthPlaceholder" authTokenKey: "TokenAuthPlaceholder"
monitoringToken: "TokenMonitoringPlaceholder" monitoringToken: "TokenMonitoringPlaceholder"
rabbitToken: "TokenRabbitPlaceholder" rabbitToken: "TokenRabbitPlaceholder"
# Mirrors app/configurations.yml params.compliance (enable without editing app/). # Mirrors legacy OneLab configurations.yml params.compliance (templated from charts/onelab/files/configurations.gotmpl).
compliance: compliance:
enabled: false enabled: false
requireElectronicSignature: true requireElectronicSignature: true
@@ -97,8 +97,8 @@ onelab:
tlsCiphers: "" tlsCiphers: ""
tlsSslVersion: "" tlsSslVersion: ""
intercom: intercom:
appid: "zxvgsagz" appid: "REPLACE_INTERCOM_APP_ID"
secret: "QUw2jEV8utIpe9DeYjOqBjhBY9VxjXddKUCISUNu" secret: "REPLACE_INTERCOM_SECRET"
features: features:
# Deprecated for LDAP: prefer onelab.ldap.enabled (either enables ldap-worker + ldap.enabled in config). # Deprecated for LDAP: prefer onelab.ldap.enabled (either enables ldap-worker + ldap.enabled in config).

View File

@@ -1,149 +1,3 @@
# Umbrella chart: Loki (SingleBinary + filesystem) + Promtail + Grafana. # Operator-facing overrides live in gitops/values/observability.yaml (see gitops/argocd/application.yaml helm.valueFiles).
# Keep hostPath below in sync with persistence.hostPath.logs in gitops/values/k3s-example.yaml. # This file is kept minimal on purpose.
{}
loki:
deploymentMode: SingleBinary
loki:
auth_enabled: false
commonConfig:
replication_factor: 1
storage:
type: filesystem
schemaConfig:
configs:
- from: "2024-04-01"
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: loki_index_
period: 24h
limits_config:
retention_period: 168h
ingestion_rate_mb: 16
ingestion_burst_size_mb: 32
singleBinary:
replicas: 1
persistence:
enabled: true
size: 10Gi
backend:
replicas: 0
read:
replicas: 0
write:
replicas: 0
ingester:
replicas: 0
querier:
replicas: 0
queryFrontend:
replicas: 0
queryScheduler:
replicas: 0
distributor:
replicas: 0
compactor:
replicas: 0
indexGateway:
replicas: 0
bloomCompactor:
replicas: 0
bloomGateway:
replicas: 0
ruler:
replicas: 0
minio:
enabled: false
lokiCanary:
enabled: false
test:
enabled: false
chunksCache:
enabled: false
resultsCache:
enabled: false
promtail:
config:
clients:
- url: http://{{ .Release.Name }}-loki-gateway.{{ .Release.Namespace }}.svc.cluster.local/loki/api/v1/push
snippets:
# Only ingest pod logs from namespace onelab (Explore / Loki stay focused on OneLab).
extraRelabelConfigs:
- action: keep
source_labels:
- __meta_kubernetes_namespace
regex: onelab
extraScrapeConfigs: |
- job_name: onelab-host-log-files
static_configs:
- targets:
- localhost
labels:
job: onelab-files
namespace: onelab
component: host-logs
__path__: /onelab-host-logs/**/*
extraVolumes:
- name: onelab-host-logs
hostPath:
path: /opt/onelab/logs
type: DirectoryOrCreate
extraVolumeMounts:
- name: onelab-host-logs
mountPath: /onelab-host-logs
readOnly: true
# Named Ingress grafana-onelab (templates/ingress-grafana-onelab.yaml). Grafana subchart ingress is disabled.
grafanaOnelabIngress:
enabled: true
className: traefik
host: grafana.k8s.selair.it
tls: true
tlsSecretName: grafana-tls-k8s-selair
clusterIssuer: letsencrypt-prod
servicePort: 80
annotations: {}
grafana:
adminUser: admin
adminPassword: changeme
# Root+CHOWN init breaks under Pod Security / restricted policies (k3s). fsGroup:472 on the pod is enough for most PVCs.
initChownData:
enabled: false
# Load dashboards from ConfigMaps labeled grafana_dashboard (see templates/configmap-dashboard-onelab-logs.yaml).
sidecar:
dashboards:
enabled: true
label: grafana_dashboard
folder: /tmp/dashboards
provider:
foldersFromFilesStructure: false
allowUiUpdates: true
datasources:
enabled: false
persistence:
enabled: true
size: 2Gi
service:
type: ClusterIP
# Required when served behind Ingress (redirects, OAuth callbacks).
grafana.ini:
server:
domain: grafana.k8s.selair.it
root_url: https://grafana.k8s.selair.it/
ingress:
enabled: false
datasources:
datasources.yaml:
apiVersion: 1
datasources:
- name: Loki
type: loki
uid: loki
url: http://{{ .Release.Name }}-loki-gateway.{{ .Release.Namespace }}.svc.cluster.local
access: proxy
isDefault: true
jsonData:
maxLines: 1000

31
gitops/values/README.md Normal file
View File

@@ -0,0 +1,31 @@
# GitOps values (operator entry point)
All environment-specific Helm input for the Argo CD `Application` should live here (plus `repoURL` / `targetRevision` in [`../argocd/application.yaml`](../argocd/application.yaml)).
## Files
| File | Purpose |
|------|---------|
| [`env-example.yaml`](env-example.yaml) | Tracked example for OneLab chart: ingress, persistence, registry pull secret wiring, **placeholder** secrets. Fork and edit hostnames/TLS names, then replace placeholders or overlay `secrets.local.yaml`. |
| [`observability.yaml`](observability.yaml) | Loki / Promtail / Grafana: retention, Promtail host paths, Grafana ingress host, **placeholder** admin password. Edit hosts/TLS together with `grafana.ini.server`. |
| [`secrets.example.yaml`](secrets.example.yaml) | Template of secret-shaped keys only — copy to `*.local.yaml` (gitignored) and reference from Argo. |
| [`instance-overrides.example.yaml`](instance-overrides.example.yaml) | Optional features (compliance, LDAP) — merge or add as another value file. |
## Argo `helm.valueFiles` (path rules)
Paths are **relative to each sources `path`** in the Application:
- Source `gitops/charts/onelab` → e.g. `../../values/env-example.yaml`, then optionally `../../values/secrets.local.yaml`.
- Source `gitops/observability` → e.g. `../../values/observability.yaml`, then optionally `../../values/observability.local.yaml`.
Later files in the list **override** earlier ones.
## Private secrets without committing them
1. Copy `secrets.example.yaml` to `secrets.local.yaml` (ignored by `*.local.yaml` at repo root).
2. Fill in real registry password, Postgres password, app tokens, Intercom, etc.
3. Add `- ../../values/secrets.local.yaml` under the onelab sources `helm.valueFiles` in your **local** Application manifest or a private overlay — or keep that change only on a private branch.
For Grafana, set `grafana.adminPassword` in a gitignored file merged with [`observability.yaml`](observability.yaml), or edit `observability.yaml` in a private fork.
See the full bootstrap narrative in [`../README.md`](../README.md).

View File

@@ -0,0 +1,48 @@
# Example environment overrides — copy patterns to a gitignored file (e.g. secrets.local.yaml)
# and add it to Argo helm.valueFiles after this file so secrets stay out of Git.
# See gitops/values/README.md and gitops/values/secrets.example.yaml.
registry:
createPullSecret: true
pullSecretName: hub-andrewalliance
server: hub.andrewalliance.com
username: public
password: "REPLACE_REGISTRY_PASSWORD"
imagePullSecrets:
- name: hub-andrewalliance
persistence:
mode: hostPath
hostPath:
data: /opt/onelab/data
logs: /opt/onelab/logs
postgresql:
auth:
password: "REPLACE_POSTGRES_PASSWORD"
onelab:
domain: "https://onelab.example.com"
secrets:
authTokenKey: "REPLACE_AUTH_TOKEN_KEY"
monitoringToken: "REPLACE_MONITORING_TOKEN"
rabbitToken: "REPLACE_RABBIT_TOKEN"
intercom:
appid: "REPLACE_INTERCOM_APP_ID"
secret: "REPLACE_INTERCOM_SECRET"
revproxy:
serviceType: ClusterIP
ingress:
enabled: true
className: traefik
host: onelab.example.com
path: /
pathType: Prefix
tls: true
tlsSecretName: onelab-tls
certManager:
clusterIssuer: letsencrypt-prod
annotations: {}

View File

@@ -1,9 +1,10 @@
# Copy to a private file (e.g. gitops/values/private-k3s.yaml, gitignored) or merge into gitops/values/k3s-example.yaml. # Copy to a private file (e.g. gitops/values/overrides.local.yaml, gitignored) or merge into gitops/values/env-example.yaml.
# #
# Argo CD: under spec.sources, for the source with path gitops/charts/onelab, add another path to helm.valueFiles # Argo CD: under spec.sources, for the source with path gitops/charts/onelab, add another path to helm.valueFiles
# (paths are relative to that chart directory), e.g.: # (paths are relative to that chart directory), e.g.:
# - ../../values/k3s-example.yaml # - ../../values/env-example.yaml
# - ../../values/private-k3s.yaml # - ../../values/secrets.local.yaml
# - ../../values/overrides.local.yaml
onelab: onelab:
compliance: compliance:

View File

@@ -1,51 +0,0 @@
# Aligned with Swarm installer defaults:
# - Registry: app/playbooks/tasks/manage-images.yml (user public, password Andrew01..Release)
# - App config sample: app/configurations.yml (placeholders + intercom block)
registry:
createPullSecret: true
pullSecretName: hub-andrewalliance
server: hub.andrewalliance.com
username: public
password: Andrew01..Release
imagePullSecrets:
- name: hub-andrewalliance
persistence:
mode: hostPath
hostPath:
data: /opt/onelab/data
logs: /opt/onelab/logs
postgresql:
auth:
password: "DBPasswordPlaceholder"
onelab:
# Public URL (must match ingress host + scheme).
domain: "https://onelab.k8s.selair.it"
secrets:
authTokenKey: "TokenAuthPlaceholder"
monitoringToken: "TokenMonitoringPlaceholder"
rabbitToken: "TokenRabbitPlaceholder"
intercom:
appid: "zxvgsagz"
secret: "QUw2jEV8utIpe9DeYjOqBjhBY9VxjXddKUCISUNu"
# ClusterIP keeps traffic via Ingress only; use NodePort instead if you need direct node:port access.
revproxy:
serviceType: ClusterIP
ingress:
enabled: true
className: traefik
host: onelab.k8s.selair.it
path: /
pathType: Prefix
tls: true
# cert-manager writes the certificate into this Secret in the release namespace
tlsSecretName: onelab-tls-k8s-selair
certManager:
clusterIssuer: letsencrypt-prod
annotations: {}

View File

@@ -0,0 +1,144 @@
# Umbrella chart: Loki (SingleBinary + filesystem) + Promtail + Grafana.
# Keep promtail hostPath below in sync with persistence.hostPath.logs in gitops/values/env-example.yaml.
loki:
deploymentMode: SingleBinary
loki:
auth_enabled: false
commonConfig:
replication_factor: 1
storage:
type: filesystem
schemaConfig:
configs:
- from: "2024-04-01"
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: loki_index_
period: 24h
limits_config:
retention_period: 168h
ingestion_rate_mb: 16
ingestion_burst_size_mb: 32
singleBinary:
replicas: 1
persistence:
enabled: true
size: 10Gi
backend:
replicas: 0
read:
replicas: 0
write:
replicas: 0
ingester:
replicas: 0
querier:
replicas: 0
queryFrontend:
replicas: 0
queryScheduler:
replicas: 0
distributor:
replicas: 0
compactor:
replicas: 0
indexGateway:
replicas: 0
bloomCompactor:
replicas: 0
bloomGateway:
replicas: 0
ruler:
replicas: 0
minio:
enabled: false
lokiCanary:
enabled: false
test:
enabled: false
chunksCache:
enabled: false
resultsCache:
enabled: false
promtail:
config:
clients:
- url: http://{{ .Release.Name }}-loki-gateway.{{ .Release.Namespace }}.svc.cluster.local/loki/api/v1/push
snippets:
extraRelabelConfigs:
- action: keep
source_labels:
- __meta_kubernetes_namespace
regex: onelab
extraScrapeConfigs: |
- job_name: onelab-host-log-files
static_configs:
- targets:
- localhost
labels:
job: onelab-files
namespace: onelab
component: host-logs
__path__: /onelab-host-logs/**/*
extraVolumes:
- name: onelab-host-logs
hostPath:
path: /opt/onelab/logs
type: DirectoryOrCreate
extraVolumeMounts:
- name: onelab-host-logs
mountPath: /onelab-host-logs
readOnly: true
grafanaOnelabIngress:
enabled: true
className: traefik
host: grafana.onelab.example.com
tls: true
tlsSecretName: grafana-onelab-tls
clusterIssuer: letsencrypt-prod
servicePort: 80
annotations: {}
grafana:
adminUser: admin
adminPassword: "REPLACE_GRAFANA_ADMIN_PASSWORD"
initChownData:
enabled: false
sidecar:
dashboards:
enabled: true
label: grafana_dashboard
folder: /tmp/dashboards
provider:
foldersFromFilesStructure: false
allowUiUpdates: true
datasources:
enabled: false
persistence:
enabled: true
size: 2Gi
service:
type: ClusterIP
grafana.ini:
server:
domain: grafana.onelab.example.com
root_url: https://grafana.onelab.example.com/
ingress:
enabled: false
datasources:
datasources.yaml:
apiVersion: 1
datasources:
- name: Loki
type: loki
uid: loki
url: http://{{ .Release.Name }}-loki-gateway.{{ .Release.Namespace }}.svc.cluster.local
access: proxy
isDefault: true
jsonData:
maxLines: 1000

View File

@@ -0,0 +1,26 @@
# Copy to a gitignored file (e.g. gitops/values/secrets.local.yaml — match *.local.yaml in repo .gitignore).
# Add it as the LAST entry in spec.sources[].helm.valueFiles for the onelab chart so these values win.
#
# Do not commit real values.
registry:
username: public
password: "YOUR_REGISTRY_PASSWORD"
postgresql:
auth:
password: "YOUR_POSTGRES_PASSWORD"
onelab:
secrets:
authTokenKey: "YOUR_AUTH_TOKEN_KEY"
monitoringToken: "YOUR_MONITORING_TOKEN"
rabbitToken: "YOUR_RABBIT_TOKEN"
intercom:
appid: "YOUR_INTERCOM_APP_ID"
secret: "YOUR_INTERCOM_SECRET"
# Optional: Grafana admin password is normally set in gitops/values/observability.yaml;
# override there or add a second gitignored value file for the observability source.
# grafana:
# adminPassword: "YOUR_GRAFANA_PASSWORD"

View File

@@ -1,16 +0,0 @@
#!/bin/bash
# Define OneLab along with the Ansible logs directory
directory="../onelab/logs/ansible"
# Check if the directory structure exists
if [ ! -d "$directory" ]; then
# If it doesn't exist, create it
mkdir -p "$directory"
fi
# To allow writing the logs
chown -R $USER "$directory"
ANSIBLE_LOG_PATH="$directory/$(date +%F)-ansible.log" ansible-playbook ./app/playbooks/install.yml

View File

@@ -1,3 +0,0 @@
#!/bin/bash
ANSIBLE_LOG_PATH=../../logs/ansible/$(date +%F)-ansible.log ansible-playbook ./restore.yml

View File

@@ -1,104 +0,0 @@
---
- name: Restoring OneLab (1.27.0)
hosts: localhost
vars_prompt:
- name: "userchoice"
prompt: "Confirm OneLab 1.27.0 restore: yes/no"
private: no
vars:
onelab_path: '../..'
onelab_images_path: '../../../onelab-images-1.27.0.tar.gz'
main_path: '../../..'
tasks:
- name: Checking if the OneLab images bundle is existing
stat:
path: "{{ onelab_images_path }}"
get_checksum: no
register: docker_images_tar
- name: Aborting the restore process
fail:
msg: Aborting the restore process
when: userchoice != "yes"
# Stop OneLab if OneLab is running
- name: Checking if OneLab is running
shell: docker stack ls | grep 'onelab' | wc -l
become: true
register: stack_count
# Stop OneLab (unkown version) if OneLab is running
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/stop-onelab.yml"
when: stack_count.stdout != "0"
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/stop-proxy.yml"
when: stack_count.stdout != "0"
# Load docker images
- name: Loading Docker images
debug:
msg:
- "Loading images could take few minutes, please do not interrupt"
when: (docker_images_tar is defined) and (docker_images_tar.stat.exists)
- name: Loading OneLab images from the tar file
shell:
docker load --input {{ onelab_images_path }}
become: true
when: (docker_images_tar is defined) and (docker_images_tar.stat.exists)
- name: Unzipping backup
shell: |
tar xzvf ./onelab.tar.gz -C ./../..
become: true
- name: Cleaning latest installation
ansible.builtin.file:
path: "{{ onelab_path }}/installation/latest"
state: absent
- name: Flagging restored version as current
ansible.builtin.copy:
src: ../../installation/1.27.0/
dest: ../../installation/latest
directory_mode: no
remote_src: yes
# Load configuration
- include_vars:
file: "{{ onelab_path }}/configurations.yml"
# Perform reconfiguration
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/reconfigure-task.yml"
# Checking if volumes are existing
- name: Getting the list of docker volumes
shell: docker volume ls
become: true
register: volumes_result
# Removing volumes
- name: Resetting postgres database & cleaning cache
shell: |
docker volume rm onelab_pgdata -f
docker volume rm onelab_rabbitmq_data -f
become: true
when: "'rabbitmq' in volumes_result.stdout or 'pgdata' in volumes_result.stdout"
# Restoring database
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/start-db-only.yml"
- name: Restoring database
shell: >
docker exec -i $(docker ps --filter "name=onelab_db|onelab-db" -q) pg_restore -Upostgres -dpostgres -v -Fc < ./db.tar.gz
become: true
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/stop-db-only.yml"
# Start OneLab if OneLab was running
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/start-proxy.yml"
when: stack_count.stdout != "0"
- include_tasks: "{{ onelab_path }}/installation/latest/app/playbooks/tasks/start-onelab.yml"
when: stack_count.stdout != "0"

View File

@@ -1,27 +0,0 @@
#!/bin/bash
sudo yum install dnf
# update the DNF package repository cache
sudo dnf makecache
# To enable EPEL repository, install the epel-release package
sudo dnf install epel-release -y
# update the DNF package repository cache again
sudo dnf makecache
# Install Ansible
sudo dnf install ansible -y
# Create the ansible log file
sudo touch /var/log/ansible.log
# Provide permissions for ansible log file
sudo chmod 666 /var/log/ansible.log
# Update Ansible hosts file for local connection
sudo sed -i '$ a localhost ansible_connection=local' /etc/ansible/hosts
# Update Ansible configuration file with logs path
sudo sed -i '13 a log_path = /var/log/ansible.log' /etc/ansible/ansible.cfg

View File

@@ -1,17 +0,0 @@
#!/bin/bash
# Install the yum-utils package (which provides the yum-config-manager utility) and set up the stable repository
sudo yum install -y yum-utils
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
# Install Docker Engine
sudo yum install docker-ce docker-ce-cli containerd.io -y
# Start Docker
sudo systemctl start docker
# Enable Docker
sudo systemctl enable docker

View File

@@ -1,22 +0,0 @@
#!/bin/bash
sudo sed -i '$ a deb http://ppa.launchpad.net/ansible/ansible/ubuntu trusty main' /etc/apt/sources.list
sudo apt-get update
sudo apt-get install -y gnupg2
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 93C4A3FD7BB9C367
sudo apt update
sudo apt install -y ansible
# Create the ansible log file
sudo touch /var/log/ansible.log
# Provide permissions for ansible log file
sudo chmod 666 /var/log/ansible.log
# Update Ansible hosts file for local connection
sudo sed -i '$ a localhost ansible_connection=local' /etc/ansible/hosts
# Update Ansible configuration file with logs path
sudo sed -i '13 a log_path = /var/log/ansible.log' /etc/ansible/ansible.cfg

View File

@@ -1,26 +0,0 @@
#!/bin/bash
# Install Dependencies
sudo apt-get update
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release -y
# Install Docker
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor --yes -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io -y
sudo systemctl start docker
sudo systemctl enable docker
# Add user to docker group
sudo usermod -aG docker $USER

View File

@@ -1,13 +0,0 @@
#!/bin/bash
sudo apt update
sudo apt install ansible
# Create the ansible log file
sudo touch /var/log/ansible.log
# Provide permissions for ansible log file
sudo chmod 666 /var/log/ansible.log

View File

@@ -1,16 +0,0 @@
#!/bin/bash
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin
sudo usermod -aG docker $USER

View File

@@ -1,13 +0,0 @@
#!/bin/bash
sudo apt update
sudo apt install ansible
# Create the ansible log file
sudo touch /var/log/ansible.log
# Provide permissions for ansible log file
sudo chmod 666 /var/log/ansible.log

View File

@@ -1,16 +0,0 @@
#!/bin/bash
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin
sudo usermod -aG docker $USER

View File

@@ -1,19 +0,0 @@
#!/bin/bash
sudo dnf install ansible -y
#Install openssl
sudo yum install openssl -y
# Create the ansible log file
sudo touch /var/log/ansible.log
# Provide permissions for ansible log file
sudo chmod 666 /var/log/ansible.log
# Update Ansible hosts file for local connection
sudo sed -i '$ a localhost ansible_connection=local' /etc/ansible/hosts
# Update Ansible configuration file with logs path
sudo sed -i '13 a log_path = /var/log/ansible.log' /etc/ansible/ansible.cfg

View File

@@ -1,21 +0,0 @@
#!/bin/bash
# Install the dnf-plugins-core package (which provides the commands to manage your DNF repositories)
sudo dnf -y install dnf-plugins-core -y
# Setup stable repository
sudo dnf config-manager \
--add-repo \
https://download.docker.com/linux/fedora/docker-ce.repo -y
# Install the latest version of Docker Engine and containerd
sudo dnf install docker-ce docker-ce-cli containerd.io -y
sudo systemctl start docker
sudo systemctl enable docker
sudo usermod -aG docker $USER

View File

@@ -1,20 +0,0 @@
#!/bin/bash
# Install Extra Packages for Linux
sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm -y
# Install Ansible
sudo yum install ansible -y
# Create the ansible log file
sudo touch /var/log/ansible.log
# Provide permissions for ansible log file
sudo chmod 666 /var/log/ansible.log
# Update Ansible hosts file for local connection
sudo sed -i '$ a localhost ansible_connection=local' /etc/ansible/hosts
# Update Ansible configuration file with logs path
sudo sed -i '13 a log_path = /var/log/ansible.log' /etc/ansible/ansible.cfg

View File

@@ -1,27 +0,0 @@
#!/bin/bash
# Install the yum-utils package
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# RHEL-7 requires the below dependencies to be installed to setup Docker
sudo yum install http://mirror.centos.org/centos/7/extras/x86_64/Packages/container-selinux-2.119.2-1.911c772.el7_8.noarch.rpm -y
sudo yum install http://mirror.centos.org/centos/7/extras/x86_64/Packages/fuse3-libs-3.6.1-4.el7.x86_64.rpm -y
sudo yum install http://mirror.centos.org/centos/7/extras/x86_64/Packages/fuse-overlayfs-0.7.2-6.el7_8.x86_64.rpm -y
sudo yum install http://mirror.centos.org/centos/7/extras/x86_64/Packages/slirp4netns-0.4.3-4.el7_8.x86_64.rpm -y
# Ended dependencies installation
sudo yum install docker-ce -y
sudo systemctl start docker
sudo systemctl enable docker
sudo usermod -aG docker $USER

View File

@@ -1,5 +0,0 @@
#!/bin/bash
sudo dnf update
sudo dnf install ansible-core

View File

@@ -1,15 +0,0 @@
#!/bin/bash
sudo dnf update -y
sudo dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo
# To verify which version of docker is available for installation
# sudo dnf list docker-ce
sudo dnf install docker-ce --nobest -y
sudo systemctl start docker
sudo systemctl enable docker
# Get current user and add to 'docker' group
sudo usermod -aG docker $USER

View File

@@ -1,5 +0,0 @@
#!/bin/bash
sudo dnf update
sudo dnf install ansible-core

View File

@@ -1,15 +0,0 @@
#!/bin/bash
sudo dnf update -y
sudo dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo
# To verify which version of docker is available for installation
# sudo dnf list docker-ce
sudo dnf install docker-ce --nobest -y
sudo systemctl start docker
sudo systemctl enable docker
# Get current user and add to 'docker' group
sudo usermod -aG docker $USER

View File

@@ -1,22 +0,0 @@
#!/bin/bash
# Install Dependencies
sudo apt update
sudo apt install software-properties-common
# Install Ansible
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt update
sudo apt install ansible
# Create the ansible log file
sudo touch /var/log/ansible.log
# Provide permissions for ansible log file
sudo chmod 666 /var/log/ansible.log
# Update Ansible hosts file for local connection
sudo sed -i '$ a localhost ansible_connection=local' /etc/ansible/hosts
# Update Ansible configuration file with logs path
sudo sed -i '13 a log_path = /var/log/ansible.log' /etc/ansible/ansible.cfg

View File

@@ -1,23 +0,0 @@
#!/bin/bash
# Install Dependencies
sudo apt-get update
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release
# Install Docker
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor --yes -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
# Add user to docker group
sudo usermod -aG docker $USER

View File

@@ -1,14 +0,0 @@
# /etc/systemd/system/onelab.service
[Unit]
Description=OneLab
Requires=docker.service
After=docker.service
[Service]
Type=simple
RemainAfterExit=yes
ExecStart={{ ansiblebin_result.stdout }} {{ playbook_dir.split('/onelab-enterprise-installer')[0].split('/onelab/installation')[0] }}/onelab/installation/latest/app/playbooks/deploy.yml
ExecStop={{ ansiblebin_result.stdout }} {{ playbook_dir.split('/onelab-enterprise-installer')[0].split('/onelab/installation')[0] }}/onelab/installation/latest/app/playbooks/stop.yml
[Install]
WantedBy=default.target