Nomad Passbolt Job
This commit is contained in:
111
README.md
Normal file
111
README.md
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
# Passbolt Nomad Deployment
|
||||||
|
|
||||||
|
This repository contains the Nomad job specification for deploying Passbolt password manager on a Nomad cluster with Consul Connect and Traefik integration.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
Before deploying Passbolt, ensure you have:
|
||||||
|
|
||||||
|
1. A Nomad cluster with Consul Connect enabled
|
||||||
|
2. Traefik configured for service routing
|
||||||
|
3. Docker volumes directory created on the target node
|
||||||
|
|
||||||
|
## Deployment Steps
|
||||||
|
|
||||||
|
### 1. Register Consul Service Defaults
|
||||||
|
|
||||||
|
Before deploying the Nomad job, you must register the service defaults with Consul:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
consul config write passbolt-service-defaults.hcl
|
||||||
|
```
|
||||||
|
|
||||||
|
This configures the protocol for the `passbolt-app` service to work with the Consul Connect ingress gateway.
|
||||||
|
|
||||||
|
### 2. Set Up Volume Permissions
|
||||||
|
|
||||||
|
The GPG volume directory requires specific permissions for Passbolt to function correctly:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create the directory if it doesn't exist
|
||||||
|
sudo mkdir -p /root/nomadvolumes/passbolt/data/gpg
|
||||||
|
|
||||||
|
# Set ownership to root with www-data group
|
||||||
|
sudo chown root:www-data /root/nomadvolumes/passbolt/data/gpg
|
||||||
|
|
||||||
|
# Set permissions to 774
|
||||||
|
sudo chmod 774 /root/nomadvolumes/passbolt/data/gpg
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Deploy the Nomad Job
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nomad run passbolt.nomad
|
||||||
|
```
|
||||||
|
|
||||||
|
## Post-Deployment Configuration
|
||||||
|
|
||||||
|
### Creating the First Admin User
|
||||||
|
|
||||||
|
After the deployment is successful, you need to create the first admin user. Connect to the Passbolt container and run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nomad alloc exec -task passbolt-app <ALLOCATION_ID> su -m -c "/usr/share/php/passbolt/bin/cake \
|
||||||
|
passbolt register_user \
|
||||||
|
-u YOUR_EMAIL \
|
||||||
|
-f YOUR_NAME \
|
||||||
|
-l YOUR_LASTNAME \
|
||||||
|
-r admin" -s /bin/sh www-data
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace:
|
||||||
|
- `<ALLOCATION_ID>` with the actual allocation ID (find it with `nomad job status passbolt`)
|
||||||
|
- `YOUR_EMAIL` with the admin email address
|
||||||
|
- `YOUR_NAME` with the admin first name
|
||||||
|
- `YOUR_LASTNAME` with the admin last name
|
||||||
|
|
||||||
|
This command will output a registration link. Follow the link to complete the user setup process, including:
|
||||||
|
- Installing the Passbolt browser extension
|
||||||
|
- Creating your passphrase
|
||||||
|
- Generating your recovery kit
|
||||||
|
|
||||||
|
For detailed instructions, see: [Passbolt Docker Installation Guide](https://www.passbolt.com/docs/hosting/install/ce/docker/)
|
||||||
|
|
||||||
|
### Importing Passwords from CSV
|
||||||
|
|
||||||
|
If you're migrating from another password manager (like Dropbox Passwords), you can import passwords using a CSV file.
|
||||||
|
|
||||||
|
Follow this community guide for the import process:
|
||||||
|
[Migrating from Dropbox Passwords to Passbolt](https://community.passbolt.com/t/migrating-from-dropbox-passwords-to-passbolt/13653)
|
||||||
|
|
||||||
|
## Access
|
||||||
|
|
||||||
|
Once deployed and configured, Passbolt will be available at:
|
||||||
|
|
||||||
|
**https://passbolt.neogenia.com.mx**
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
The deployment consists of three main groups:
|
||||||
|
|
||||||
|
1. **ingress-group**: Consul Connect ingress gateway with Traefik integration for external routing
|
||||||
|
2. **database**: MariaDB 10.11 for data persistence
|
||||||
|
3. **passbolt**: The main Passbolt application with Consul Connect sidecar for secure service mesh communication
|
||||||
|
|
||||||
|
## Volumes
|
||||||
|
|
||||||
|
The deployment uses the following persistent volumes:
|
||||||
|
|
||||||
|
- `/root/nomadvolumes/passbolt/data/mysql` - MariaDB database files
|
||||||
|
- `/root/nomadvolumes/passbolt/data/gpg` - GPG keys (requires special permissions)
|
||||||
|
- `/root/nomadvolumes/passbolt/data/jwt` - JWT tokens
|
||||||
|
|
||||||
|
## Security Notes
|
||||||
|
|
||||||
|
- Database credentials are configured in the Nomad job file. Update these for production use.
|
||||||
|
- All service-to-service communication uses Consul Connect for mTLS encryption
|
||||||
|
- Traefik handles TLS termination with automatic certificate generation via Let's Encrypt
|
||||||
|
|
||||||
|
## Additional Notes
|
||||||
|
|
||||||
|
- This repo contains the original docker-compose yml file as a reference but it is not needed to run the nomad job
|
||||||
3
passbolt-service-defaults.hcl
Normal file
3
passbolt-service-defaults.hcl
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
Kind = "service-defaults"
|
||||||
|
Name = "passbolt-app"
|
||||||
|
Protocol = "http"
|
||||||
214
passbolt.nomad
Normal file
214
passbolt.nomad
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
job "passbolt" {
|
||||||
|
|
||||||
|
datacenters = ["dc1"]
|
||||||
|
type = "service"
|
||||||
|
|
||||||
|
constraint {
|
||||||
|
attribute = "${node.unique.name}"
|
||||||
|
value = "mercury-nomad"
|
||||||
|
}
|
||||||
|
|
||||||
|
group "ingress-group" {
|
||||||
|
count = 1
|
||||||
|
|
||||||
|
network {
|
||||||
|
mode = "bridge"
|
||||||
|
|
||||||
|
port "inbound" {
|
||||||
|
to = 8080
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
service {
|
||||||
|
name = "passbolt-ingress"
|
||||||
|
port = "inbound"
|
||||||
|
|
||||||
|
tags = [
|
||||||
|
"traefikcontabo.enable=true",
|
||||||
|
"traefikcontabo.http.middlewares.passbolt-redirectscheme.redirectscheme.scheme=https",
|
||||||
|
"traefikcontabo.http.middlewares.passbolt-redirectscheme.redirectscheme.permanent=true",
|
||||||
|
"traefikcontabo.http.routers.passbolt-http.rule=Host(`passbolt.neogenia.com.mx`)",
|
||||||
|
"traefikcontabo.http.routers.passbolt-http.entrypoints=http",
|
||||||
|
"traefikcontabo.http.routers.passbolt-http.middlewares=passbolt-redirectscheme",
|
||||||
|
"traefikcontabo.http.routers.passbolt-https.rule=Host(`passbolt.neogenia.com.mx`)",
|
||||||
|
"traefikcontabo.http.routers.passbolt-https.entrypoints=https",
|
||||||
|
"traefikcontabo.http.routers.passbolt-https.tls=true",
|
||||||
|
"traefikcontabo.http.routers.passbolt-https.tls.certresolver=myresolver",
|
||||||
|
]
|
||||||
|
|
||||||
|
connect {
|
||||||
|
gateway {
|
||||||
|
ingress {
|
||||||
|
listener {
|
||||||
|
port = 8080
|
||||||
|
protocol = "http"
|
||||||
|
service {
|
||||||
|
name = "passbolt-app"
|
||||||
|
hosts = ["passbolt.neogenia.com.mx"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
group "database" {
|
||||||
|
count = 1
|
||||||
|
|
||||||
|
update {
|
||||||
|
max_parallel = 1
|
||||||
|
min_healthy_time = "30s"
|
||||||
|
healthy_deadline = "5m"
|
||||||
|
progress_deadline = "10m"
|
||||||
|
auto_revert = true
|
||||||
|
}
|
||||||
|
|
||||||
|
restart {
|
||||||
|
attempts = 3
|
||||||
|
interval = "5m"
|
||||||
|
delay = "30s"
|
||||||
|
mode = "delay"
|
||||||
|
}
|
||||||
|
|
||||||
|
network {
|
||||||
|
mode = "bridge"
|
||||||
|
}
|
||||||
|
|
||||||
|
task "mariadb" {
|
||||||
|
driver = "docker"
|
||||||
|
|
||||||
|
config {
|
||||||
|
image = "mariadb:10.11"
|
||||||
|
volumes = [
|
||||||
|
"/root/nomadvolumes/passbolt/data/mysql:/var/lib/mysql"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
env {
|
||||||
|
MYSQL_RANDOM_ROOT_PASSWORD = "true"
|
||||||
|
MYSQL_DATABASE = "passbolt"
|
||||||
|
MYSQL_USER = "passbolt"
|
||||||
|
MYSQL_PASSWORD = "akjsdhfkrTThasgh5qw7"
|
||||||
|
}
|
||||||
|
|
||||||
|
resources {
|
||||||
|
cpu = 500
|
||||||
|
memory = 512
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
service {
|
||||||
|
name = "passbolt-db"
|
||||||
|
port = 3306
|
||||||
|
|
||||||
|
connect {
|
||||||
|
sidecar_service {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
group "passbolt" {
|
||||||
|
count = 1
|
||||||
|
|
||||||
|
update {
|
||||||
|
max_parallel = 1
|
||||||
|
min_healthy_time = "30s"
|
||||||
|
healthy_deadline = "10m"
|
||||||
|
progress_deadline = "15m"
|
||||||
|
auto_revert = true
|
||||||
|
}
|
||||||
|
|
||||||
|
restart {
|
||||||
|
attempts = 5
|
||||||
|
interval = "5m"
|
||||||
|
delay = "30s"
|
||||||
|
mode = "delay"
|
||||||
|
}
|
||||||
|
|
||||||
|
reschedule {
|
||||||
|
attempts = 10
|
||||||
|
interval = "1h"
|
||||||
|
delay = "30s"
|
||||||
|
delay_function = "exponential"
|
||||||
|
max_delay = "120s"
|
||||||
|
unlimited = false
|
||||||
|
}
|
||||||
|
|
||||||
|
network {
|
||||||
|
mode = "bridge"
|
||||||
|
port "expose" {
|
||||||
|
to = -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task "passbolt-app" {
|
||||||
|
driver = "docker"
|
||||||
|
|
||||||
|
config {
|
||||||
|
image = "passbolt/passbolt:latest-ce"
|
||||||
|
volumes = [
|
||||||
|
"/root/nomadvolumes/passbolt/data/gpg:/etc/passbolt/gpg",
|
||||||
|
"/root/nomadvolumes/passbolt/data/jwt:/etc/passbolt/jwt"
|
||||||
|
]
|
||||||
|
command = "/usr/bin/wait-for.sh"
|
||||||
|
args = [
|
||||||
|
"-t",
|
||||||
|
"0",
|
||||||
|
"127.0.0.1:3306",
|
||||||
|
"--",
|
||||||
|
"/docker-entrypoint.sh"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
env {
|
||||||
|
APP_FULL_BASE_URL = "https://passbolt.neogenia.com.mx"
|
||||||
|
DATASOURCES_DEFAULT_HOST = "127.0.0.1"
|
||||||
|
DATASOURCES_DEFAULT_PORT = "3306"
|
||||||
|
DATASOURCES_DEFAULT_USERNAME = "passbolt"
|
||||||
|
DATASOURCES_DEFAULT_PASSWORD = "akjsdhfkrTThasgh5qw7"
|
||||||
|
DATASOURCES_DEFAULT_DATABASE = "passbolt"
|
||||||
|
}
|
||||||
|
|
||||||
|
resources {
|
||||||
|
cpu = 500
|
||||||
|
memory = 512
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
service {
|
||||||
|
name = "passbolt-app"
|
||||||
|
port = 80
|
||||||
|
|
||||||
|
connect {
|
||||||
|
sidecar_service {
|
||||||
|
proxy {
|
||||||
|
upstreams {
|
||||||
|
destination_name = "passbolt-db"
|
||||||
|
local_bind_port = 3306
|
||||||
|
}
|
||||||
|
expose {
|
||||||
|
path {
|
||||||
|
path = "/healthcheck/status.json"
|
||||||
|
protocol = "http"
|
||||||
|
local_path_port = 80
|
||||||
|
listener_port = "expose"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
check {
|
||||||
|
expose = true
|
||||||
|
type = "http"
|
||||||
|
path = "/healthcheck/status.json"
|
||||||
|
interval = "30s"
|
||||||
|
timeout = "5s"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
48
passbolt.yml
Normal file
48
passbolt.yml
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: mariadb:10.11
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
MYSQL_RANDOM_ROOT_PASSWORD: "true"
|
||||||
|
MYSQL_DATABASE: "passbolt"
|
||||||
|
MYSQL_USER: "passbolt"
|
||||||
|
MYSQL_PASSWORD: "P4ssb0lt"
|
||||||
|
volumes:
|
||||||
|
- database_volume:/var/lib/mysql
|
||||||
|
|
||||||
|
passbolt:
|
||||||
|
image: passbolt/passbolt:latest-ce
|
||||||
|
#Alternatively you can use rootless:
|
||||||
|
#image: passbolt/passbolt:latest-ce-non-root
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
environment:
|
||||||
|
APP_FULL_BASE_URL: https://passbolt.local
|
||||||
|
DATASOURCES_DEFAULT_HOST: "db"
|
||||||
|
DATASOURCES_DEFAULT_USERNAME: "passbolt"
|
||||||
|
DATASOURCES_DEFAULT_PASSWORD: "P4ssb0lt"
|
||||||
|
DATASOURCES_DEFAULT_DATABASE: "passbolt"
|
||||||
|
volumes:
|
||||||
|
- gpg_volume:/etc/passbolt/gpg
|
||||||
|
- jwt_volume:/etc/passbolt/jwt
|
||||||
|
command:
|
||||||
|
[
|
||||||
|
"/usr/bin/wait-for.sh",
|
||||||
|
"-t",
|
||||||
|
"0",
|
||||||
|
"db:3306",
|
||||||
|
"--",
|
||||||
|
"/docker-entrypoint.sh",
|
||||||
|
]
|
||||||
|
ports:
|
||||||
|
- 80:80
|
||||||
|
- 443:443
|
||||||
|
#Alternatively for non-root images:
|
||||||
|
# - 80:8080
|
||||||
|
# - 443:4433
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
database_volume:
|
||||||
|
gpg_volume:
|
||||||
|
jwt_volume:
|
||||||
Reference in New Issue
Block a user