Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions 03_container_layer/docker/admin/rocketchat/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.env
*.env
*.key
*.pem
README.md
5 changes: 5 additions & 0 deletions 03_container_layer/docker/admin/rocketchat/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
RC_BASE_URL=http://localhost:3000
RC_ADMIN_USER=rc-admin
RC_ADMIN_PASS=Admin1234!
RC_ADMIN_EMAIL=admin@range42.local
HTTP_PORT=3000
28 changes: 28 additions & 0 deletions 03_container_layer/docker/admin/rocketchat/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#
# ISSUE 147
#

#
# BUILDER — node:20-alpine (same base as official Rocket.Chat Dockerfile)
#
FROM node:20-alpine AS builder

RUN apk add --no-cache jq && \
wget -q https://github.com/mikefarah/yq/releases/download/v4.44.1/yq_linux_amd64 \
-O /usr/bin/yq && chmod +x /usr/bin/yq

COPY provisioning/ /provisioning/
RUN chmod +x /provisioning/init.sh

#
# RUNTIME — rocketchat/rocket.chat:latest (Alpine/Node-based)
#
FROM rocketchat/rocket.chat:latest AS runtime

USER root

COPY --from=builder /usr/bin/yq /usr/bin/yq
COPY --from=builder /usr/bin/jq /usr/bin/jq
COPY --from=builder /provisioning/ /provisioning/

ENTRYPOINT ["/provisioning/init.sh"]
91 changes: 91 additions & 0 deletions 03_container_layer/docker/admin/rocketchat/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#
# ISSUE 147
#

SERVICE = rocketchat
PROVISIONER = rocketchat-provisioner
DEBUG_SERVICE = $(SERVICE)-debug

.PHONY: help up down stop stop-debug-build build rebuild build-up rebuild-up tokens reprovision term term-debug-build clean print

help:
@echo ""
@echo ""
@echo " Available : "
@echo ""
@echo " make up - run $(SERVICE) stack in background"
@echo " make down - down $(SERVICE) stack"
@echo " make stop - stop $(SERVICE) "
@echo " make stop-debug-build - stop $(DEBUG_SERVICE) "
@echo ""
@echo " make build - build $(SERVICE) image"
@echo " make build-up - build $(SERVICE) image then run"
@echo ""
@echo " make rebuild - full rebuild $(SERVICE) without cache"
@echo " make rebuild-up - full rebuild $(SERVICE) without cache then run"
@echo ""
@echo " make tokens - print generated personal access tokens"
@echo " make term - open shell in $(SERVICE) container"
@echo " make term-debug-build - build and get term on $(DEBUG_SERVICE) "
@echo " make clean - delete all containers, images, volumes and unused network"
@echo " make print - print this help"
@echo ""
@echo ""

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

up:
docker compose up -d $(SERVICE)
down:
docker compose down
stop:
docker compose stop $(SERVICE) # stop only - main

stop-debug-build :
docker compose stop $(DEBUG_SERVICE) # stop only debug
docker compose rm -sf $(DEBUG_SERVICE)

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

build:
docker compose build

rebuild:
docker compose down
docker compose build --no-cache

# # # # # # # # # # # #

build-up:
docker compose build
docker compose up -d

rebuild-up:
docker compose down
docker compose build --no-cache
docker compose up -d

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

tokens:
docker run --rm -v rocketchat-tokens:/tokens alpine cat /tokens/tokens.txt

reprovision:
docker run --rm -v rocketchat-tokens:/tokens alpine rm -f /tokens/.provisioned
docker compose up $(PROVISIONER)

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

clean:
docker compose down -v --rmi all

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

term:
docker exec -it $(SERVICE) /bin/sh

term-debug-build:
docker compose up --build -d $(DEBUG_SERVICE)
docker exec -it $(DEBUG_SERVICE) /bin/sh

print: help
169 changes: 169 additions & 0 deletions 03_container_layer/docker/admin/rocketchat/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
# Rocket.Chat — Standalone Docker Deployment

Issue 147. Dockerized Rocket.Chat with MongoDB replica set and automated user / personal-access-token provisioning.

---

## Prerequisites

| Requirement | Version |
|---|---|
| Docker | 24+ |
| Docker Compose (plugin) | v2.20+ |
| `make` | any |

---

## Quick Start

```sh
# 1. Copy and edit environment file
cp .env.example .env
$EDITOR .env

# 2. Build and start the full stack
make build-up

# 3. Wait for the provisioner to finish, then check tokens
make tokens
```

> **MongoDB replica set** initialises automatically via the `mongo-init-replica` one-shot container. No manual `rs.initiate()` step is needed.

The web UI is available at `http://localhost:3000` (or `RC_BASE_URL`).
Default admin credentials: `rc-admin` / `Admin1234!` (change in `.env`).

---

## Build & Push

```sh
# Build provisioner image
make build

# Full rebuild without cache
make rebuild

# Tag and push (adjust registry as needed)
docker tag rocketchat-provisioner registry.example.com/range42/rocketchat-provisioner:latest
docker push registry.example.com/range42/rocketchat-provisioner:latest
```

---

## Declaring Users

Edit `provisioning/users.yml` before first deployment:

```yaml
# !! CHANGE ALL PASSWORDS BEFORE DEPLOYING !!

admins:
- username: rc-admin2
email: admin2@range42.local
password: "Admin1234!"
name: "RC Admin 2"

users:
- username: trainee01
email: trainee01@range42.local
password: "Trainee1234!"
name: "Trainee 01"
```

The primary admin (`rc-admin`) is created automatically via the `ADMIN_USERNAME` environment variable. The users listed in `users.yml` are **additional** accounts.

---

## Token Retrieval

Personal access tokens are written to `/tokens/tokens.txt` (inside the `rocketchat-tokens` volume) at the end of provisioning.

```sh
# Print all tokens
make tokens

# Or read directly from the volume
docker run --rm -v rocketchat_rocketchat-tokens:/tokens:ro busybox cat /tokens/tokens.txt
```

Each line has the format:

```
username:personalAccessToken
```

---

## API Usage Examples

```sh
# Get server info (no auth needed)
curl http://localhost:3000/api/v1/info

# List channels (authenticated)
TOKEN="<paste token from tokens.txt>"
USER_ID="<userId — retrieve via login endpoint>"

curl -X GET http://localhost:3000/api/v1/channels.list \
-H "X-Auth-Token: ${TOKEN}" \
-H "X-User-Id: ${USER_ID}"

# Post a message
curl -X POST http://localhost:3000/api/v1/chat.postMessage \
-H "X-Auth-Token: ${TOKEN}" \
-H "X-User-Id: ${USER_ID}" \
-H "Content-Type: application/json" \
-d '{"channel":"#general","text":"Hello from range42!"}'
```

---

## Environment Variables

| Variable | Default | Description |
|---|---|---|
| `RC_BASE_URL` | `http://localhost:3000` | Public URL (used by Rocket.Chat as `ROOT_URL`) |
| `RC_ADMIN_USER` | `rc-admin` | Initial admin username |
| `RC_ADMIN_PASS` | `Admin1234!` | Initial admin password |
| `RC_ADMIN_EMAIL` | `admin@range42.local` | Initial admin email |
| `HTTP_PORT` | `3000` | Host port mapped to Rocket.Chat |

---

## Troubleshooting

### MongoDB replica set issues

**Symptom:** Rocket.Chat exits with `MongoServerError: not primary`.

**Cause:** The replica set has not been initialised yet. The `mongo-init-replica` container handles this automatically, but it requires MongoDB to be healthy first.

**Fix:**
```sh
# Check mongo-init-replica logs
docker logs rocketchat-mongo-init

# Force re-init manually if needed
docker exec rocketchat-mongodb mongosh --eval \
"rs.initiate({ _id: 'rs0', members: [{ _id: 0, host: 'mongodb:27017' }] })"
```

### Provisioner exits with auth error

**Symptom:** `[init] ERROR: Failed to authenticate as admin.`

**Cause:** Rocket.Chat is not yet fully ready (it can take 60–90 s on first boot).

**Fix:** The provisioner will be restarted automatically by Docker Compose if `restart: "no"` is overridden, or you can re-run it manually:
```sh
docker compose run --rm provisioner
```

### Tokens already exist

If the provisioner runs a second time, `generatePersonalAccessToken` will fail for tokens named `api-token` that already exist. This is handled gracefully — a warning is printed and the existing token is left in place. Re-provision with a clean volume to regenerate:
```sh
docker volume rm rocketchat_rocketchat-tokens
docker compose run --rm provisioner
```
96 changes: 96 additions & 0 deletions 03_container_layer/docker/admin/rocketchat/compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#
# ISSUE 147
#

services:

mongodb:
image: mongo:6.0
container_name: rocketchat-mongodb
command: mongod --replSet rs0 --oplogSize 128
volumes:
- rocketchat-mongodb-data:/data/db
healthcheck:
test: ["CMD", "mongosh", "--eval", "try { rs.status().ok } catch(e) { 0 }"]
interval: 10s
timeout: 5s
retries: 10
start_period: 20s
restart: unless-stopped

mongo-init-replica:
image: mongo:6.0
container_name: rocketchat-mongo-init
command: >
bash -c "
until mongosh mongodb:27017/admin --eval 'db.adminCommand(\"ping\")' >/dev/null 2>&1; do sleep 2; done;
mongosh mongodb:27017/admin --eval '
try { rs.status().ok } catch(e) {
rs.initiate({ _id: \"rs0\", members: [{ _id: 0, host: \"mongodb:27017\" }] })
}';
until mongosh mongodb:27017/admin --eval 'rs.isMaster().ismaster' 2>/dev/null | grep -q true; do sleep 2; done;
echo \"Replica set PRIMARY ready\"
"
depends_on:
mongodb:
condition: service_healthy
restart: "no"

rocketchat: &main
image: rocketchat/rocket.chat:latest
container_name: rocketchat
environment:
MONGO_URL: "mongodb://mongodb:27017/rocketchat?replicaSet=rs0"
MONGO_OPLOG_URL: "mongodb://mongodb:27017/local?replicaSet=rs0"
ROOT_URL: ${RC_BASE_URL:-http://localhost:3000}
PORT: "3000"
DEPLOY_PLATFORM: docker
ADMIN_USERNAME: ${RC_ADMIN_USER:-rc-admin}
ADMIN_PASS: ${RC_ADMIN_PASS:-Admin1234!}
ADMIN_EMAIL: ${RC_ADMIN_EMAIL:-admin@range42.local}
OVERWRITE_SETTING_Show_Setup_Wizard: completed
volumes:
- rocketchat-uploads:/app/uploads
ports:
- "${HTTP_PORT:-3000}:3000"
depends_on:
mongodb:
condition: service_healthy
mongo-init-replica:
condition: service_completed_successfully
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/api/v1/info"]
interval: 20s
timeout: 10s
retries: 15
start_period: 60s
restart: unless-stopped
#
# #### #### do not remove.
#
# debug:
# <<: *main
# container_name: rocketchat-debug
# command: ["sleep", "infinity"]

provisioner:
build:
context: .
dockerfile: Dockerfile
container_name: rocketchat-provisioner
environment:
RC_URL: http://rocketchat:3000
RC_ADMIN_USER: ${RC_ADMIN_USER:-rc-admin}
RC_ADMIN_PASS: ${RC_ADMIN_PASS:-Admin1234!}
USERS_FILE: /provisioning/users.yml
volumes:
- rocketchat-tokens:/tokens
depends_on:
rocketchat:
condition: service_healthy
restart: "no"

volumes:
rocketchat-mongodb-data:
rocketchat-uploads:
rocketchat-tokens:
Loading