OS Apps: Docmost and Cachet

Published: Aug 6, 2024 by Isaac Johnson

Today we’ll take some time to look at two Open-Source applications that have been on my list; Cachet and Docmost. Docmost is an internal documentation suite - this is a bit like Docusaurus but just for internal. I did find it is surprisingly usable after figuring out the command syntax.

Cachet is a “Status Dashboard” you can use to indicate the overall status of your systems. Following the whole global Crowdstrike outage I think we are all thinking more about proper Operations and SRE toolings that can give our customer bases live updates. This is an older suite but very usable (a keeper, imho).

Let’s dig in!

Docmost

Looking at Docmost in Github we can see it’s an Open-Source Documentation and Wiki offering presently in Beta.

The installation guide shows a rather straight-forward Docker Compose setup that includes PostgreSQL and Redis

version: "3"

services:
  docmost:
    image: docmost/docmost:latest
    depends_on:
      - db
      - redis
    environment:
      APP_URL: "http://localhost:3000"
      APP_SECRET: "REPLACE_WITH_LONG_SECRET"
      DATABASE_URL: "postgresql://docmost:STRONG_DB_PASSWORD@db:5432/docmost?schema=public"
      REDIS_URL: "redis://redis:6379"
    ports:
      - "3000:3000"
    restart: unless-stopped
    volumes:
      - docmost:/app/data/storage

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: docmost
      POSTGRES_USER: docmost
      POSTGRES_PASSWORD: STRONG_DB_PASSWORD
    restart: unless-stopped
    volumes:
      - db_data:/var/lib/postgresql/data

  redis:
    image: redis:7.2-alpine
    restart: unless-stopped
    volumes:
      - redis_data:/data

volumes:
  docmost:
  db_data:
  redis_data:

Let’s start with our Dockerhost

builder@builder-T100:~$ git clone https://github.com/docmost/docmost.git
Cloning into 'docmost'...
remote: Enumerating objects: 6228, done.
remote: Counting objects: 100% (883/883), done.
remote: Compressing objects: 100% (497/497), done.
remote: Total 6228 (delta 468), reused 685 (delta 360), pack-reused 5345
Receiving objects: 100% (6228/6228), 2.34 MiB | 9.47 MiB/s, done.
Resolving deltas: 100% (3717/3717), done.
builder@builder-T100:~$ cd docmost/
builder@builder-T100:~/docmost$ pwd
/home/builder/docmost

I’ll use some secrets. As this is for internal testing, I don’t mind sharing

builder@builder-T100:~/docmost$ vi docker-compose.yml
builder@builder-T100:~/docmost$ git diff
diff --git a/docker-compose.yml b/docker-compose.yml
index f7fbc60..545f768 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -7,12 +7,12 @@ services:
       - db
       - redis
     environment:
-      APP_URL: 'http://localhost:3000'
-      APP_SECRET: 'REPLACE_WITH_LONG_SECRET'
-      DATABASE_URL: 'postgresql://docmost:STRONG_DB_PASSWORD@db:5432/docmost?schema=public'
+      APP_URL: 'http://localhost:3220'
+      APP_SECRET: '0a447e91bb8e1155cf579abf9d7dd2ee9932cc03'
+      DATABASE_URL: 'postgresql://docmost:D0cm0st4FunNPr0fit_2024@db:5432/docmost?schema=public'
       REDIS_URL: 'redis://redis:6379'
     ports:
-      - "3000:3000"
+      - "3220:3000"
     restart: unless-stopped
     volumes:
       - docmost:/app/data/storage
@@ -22,7 +22,7 @@ services:
     environment:
       POSTGRES_DB: docmost
       POSTGRES_USER: docmost
-      POSTGRES_PASSWORD: STRONG_DB_PASSWORD
+      POSTGRES_PASSWORD: D0cm0st4FunNPr0fit_2024
     restart: unless-stopped
     volumes:
       - db_data:/var/lib/postgresql/data

We can now use docker compuse up to test it interactively

builder@builder-T100:~/docmost$ docker compose up
[+] Running 38/38
 ✔ db 11 layers [⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿]      0B/0B      Pulled                                                                                                                                                                                                                                                 8.0s
   ✔ c6a83fedfae6 Pull complete                                                                                                                                                                                                                                                                      0.5s
   ✔ 4f325da6b465 Pull complete                                                                                                                                                                                                                                                                      0.6s
   ✔ 3b9c004462cc Pull complete                                                                                                                                                                                                                                                                      0.7s
   ✔ b79435b3f24e Pull complete                                                                                                                                                                                                                                                                      0.7s
   ✔ 826bb0ac1004 Pull complete                                                                                                                                                                                                                                                                      0.7s
   ✔ 877cab0f2b20 Pull complete                                                                                                                                                                                                                                                                      6.6s
   ✔ 8dc019278051 Pull complete                                                                                                                                                                                                                                                                      6.8s
   ✔ 8b290b70c03c Pull complete                                                                                                                                                                                                                                                                      6.8s
   ✔ 5349cd158aa9 Pull complete                                                                                                                                                                                                                                                                      6.9s
   ✔ d45300484531 Pull complete                                                                                                                                                                                                                                                                      6.9s
   ✔ b40d58adb5bb Pull complete                                                                                                                                                                                                                                                                      6.9s
 ✔ redis 7 layers [⣿⣿⣿⣿⣿⣿⣿]      0B/0B      Pulled                                                                                                                                                                                                                                                   7.4s
   ✔ b829e07e5656 Pull complete                                                                                                                                                                                                                                                                      3.5s
   ✔ e41a7e970d15 Pull complete                                                                                                                                                                                                                                                                      4.1s
   ✔ 709f8b69d3d2 Pull complete                                                                                                                                                                                                                                                                      4.2s
   ✔ 6302448af5c9 Pull complete                                                                                                                                                                                                                                                                      5.6s
   ✔ ac0f4f36e8a5 Pull complete                                                                                                                                                                                                                                                                      5.8s
   ✔ 4f4fb700ef54 Pull complete                                                                                                                                                                                                                                                                      5.9s
   ✔ e2170ed175fe Pull complete                                                                                                                                                                                                                                                                      6.0s
 ✔ docmost 17 layers [⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿]      0B/0B      Pulled                                                                                                                                                                                                                                     30.1s
   ✔ d25f557d7f31 Pull complete                                                                                                                                                                                                                                                                      1.7s
   ✔ 9e36186fec5a Pull complete                                                                                                                                                                                                                                                                      4.9s
   ✔ 14d453f422e7 Pull complete                                                                                                                                                                                                                                                                      5.3s
   ✔ 24ff74239155 Pull complete                                                                                                                                                                                                                                                                      5.6s
   ✔ 6090dae590f9 Pull complete                                                                                                                                                                                                                                                                      6.1s
   ✔ 09e51c1c5bea Pull complete                                                                                                                                                                                                                                                                      6.2s
   ✔ e0e5dbeb5446 Pull complete                                                                                                                                                                                                                                                                      6.5s
   ✔ 224bcac0ea04 Pull complete                                                                                                                                                                                                                                                                      6.7s
   ✔ 2d3623b3db5e Pull complete                                                                                                                                                                                                                                                                      6.8s
   ✔ 923f2cc20ace Pull complete                                                                                                                                                                                                                                                                      6.9s
   ✔ 670f41d1f6de Pull complete                                                                                                                                                                                                                                                                      6.9s
   ✔ ced7f1cf0abb Pull complete                                                                                                                                                                                                                                                                      6.9s
   ✔ df0a8ee59fd4 Pull complete                                                                                                                                                                                                                                                                      7.0s
   ✔ 52a4cba16b4e Pull complete                                                                                                                                                                                                                                                                      7.5s
   ✔ c16fe6c36c08 Pull complete                                                                                                                                                                                                                                                                      7.6s
   ✔ 75ce62c81610 Pull complete                                                                                                                                                                                                                                                                     29.0s
   ✔ fc663811fc74 Pull complete                                                                                                                                                                                                                                                                     29.1s
[+] Building 0.0s (0/0)
[+] Running 7/7
 ✔ Network docmost_default      Created                                                                                                                                                                                                                                                              0.3s
 ✔ Volume "docmost_docmost"     Created                                                                                                                                                                                                                                                              0.0s
 ✔ Volume "docmost_db_data"     Created                                                                                                                                                                                                                                                              0.0s
 ✔ Volume "docmost_redis_data"  Created                                                                                                                                                                                                                                                              0.0s
 ✔ Container docmost-db-1       Created                                                                                                                                                                                                                                                              0.3s
 ✔ Container docmost-redis-1    Created                                                                                                                                                                                                                                                              0.3s
 ✔ Container docmost-docmost-1  Created                                                                                                                                                                                                                                                              0.2s
Attaching to docmost-db-1, docmost-docmost-1, docmost-redis-1
docmost-redis-1    | 1:C 29 Jul 2024 11:34:19.357 * oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
docmost-redis-1    | 1:C 29 Jul 2024 11:34:19.358 * Redis version=7.2.5, bits=64, commit=00000000, modified=0, pid=1, just started
docmost-redis-1    | 1:C 29 Jul 2024 11:34:19.358 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
docmost-redis-1    | 1:M 29 Jul 2024 11:34:19.358 * monotonic clock: POSIX clock_gettime
docmost-redis-1    | 1:M 29 Jul 2024 11:34:19.360 * Running mode=standalone, port=6379.
docmost-redis-1    | 1:M 29 Jul 2024 11:34:19.361 * Server initialized
docmost-redis-1    | 1:M 29 Jul 2024 11:34:19.361 * Ready to accept connections tcp
docmost-db-1       | The files belonging to this database system will be owned by user "postgres".
docmost-db-1       | This user must also own the server process.
docmost-db-1       |
docmost-db-1       | The database cluster will be initialized with locale "en_US.utf8".
docmost-db-1       | The default database encoding has accordingly been set to "UTF8".
docmost-db-1       | The default text search configuration will be set to "english".
docmost-db-1       |
docmost-db-1       | Data page checksums are disabled.
docmost-db-1       |
docmost-db-1       | fixing permissions on existing directory /var/lib/postgresql/data ... ok
docmost-db-1       | creating subdirectories ... ok
docmost-db-1       | selecting dynamic shared memory implementation ... posix
docmost-db-1       | selecting default max_connections ... 100
docmost-db-1       | selecting default shared_buffers ... 128MB
docmost-db-1       | selecting default time zone ... UTC
docmost-db-1       | creating configuration files ... ok
docmost-db-1       | running bootstrap script ... ok
docmost-db-1       | sh: locale: not found
docmost-db-1       | 2024-07-29 11:34:20.475 UTC [35] WARNING:  no usable system locales were found
docmost-db-1       | performing post-bootstrap initialization ... ok
docmost-docmost-1  |
docmost-docmost-1  | > docmost@0.2.8 start /app
docmost-docmost-1  | > pnpm --filter ./apps/server run start:prod
docmost-docmost-1  |
docmost-db-1       | initdb: warning: enabling "trust" authentication for local connections
docmost-db-1       | initdb: hint: You can change this by editing pg_hba.conf or using the option -A, or --auth-local and --auth-host, the next time you run initdb.
docmost-db-1       | syncing data to disk ... ok
docmost-db-1       |
docmost-db-1       |
docmost-db-1       | Success. You can now start the database server using:
docmost-db-1       |
docmost-db-1       |     pg_ctl -D /var/lib/postgresql/data -l logfile start
docmost-db-1       |
docmost-db-1       | waiting for server to start....2024-07-29 11:34:22.021 UTC [41] LOG:  starting PostgreSQL 16.3 on x86_64-pc-linux-musl, compiled by gcc (Alpine 13.2.1_git20240309) 13.2.1 20240309, 64-bit
docmost-db-1       | 2024-07-29 11:34:22.039 UTC [41] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
docmost-db-1       | 2024-07-29 11:34:22.049 UTC [44] LOG:  database system was shut down at 2024-07-29 11:34:21 UTC
docmost-db-1       | 2024-07-29 11:34:22.055 UTC [41] LOG:  database system is ready to accept connections
docmost-db-1       |  done
docmost-db-1       | server started
docmost-db-1       | CREATE DATABASE
docmost-db-1       |
docmost-db-1       |
docmost-db-1       | /usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
docmost-db-1       |
docmost-db-1       | 2024-07-29 11:34:22.456 UTC [41] LOG:  received fast shutdown request
docmost-db-1       | waiting for server to shut down....2024-07-29 11:34:22.460 UTC [41] LOG:  aborting any active transactions
docmost-db-1       | 2024-07-29 11:34:22.462 UTC [41] LOG:  background worker "logical replication launcher" (PID 47) exited with exit code 1
docmost-db-1       | 2024-07-29 11:34:22.464 UTC [42] LOG:  shutting down
docmost-db-1       | 2024-07-29 11:34:22.472 UTC [42] LOG:  checkpoint starting: shutdown immediate
docmost-db-1       | 2024-07-29 11:34:22.549 UTC [42] LOG:  checkpoint complete: wrote 924 buffers (5.6%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.058 s, sync=0.014 s, total=0.085 s; sync files=301, longest=0.002 s, average=0.001 s; distance=4267 kB, estimate=4267 kB; lsn=0/191AA98, redo lsn=0/191AA98
docmost-db-1       | 2024-07-29 11:34:22.557 UTC [41] LOG:  database system is shut down
docmost-db-1       |  done
docmost-db-1       | server stopped
docmost-db-1       |
docmost-db-1       | PostgreSQL init process complete; ready for start up.
docmost-db-1       |
docmost-db-1       | 2024-07-29 11:34:22.801 UTC [1] LOG:  starting PostgreSQL 16.3 on x86_64-pc-linux-musl, compiled by gcc (Alpine 13.2.1_git20240309) 13.2.1 20240309, 64-bit
docmost-db-1       | 2024-07-29 11:34:22.801 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
docmost-db-1       | 2024-07-29 11:34:22.801 UTC [1] LOG:  listening on IPv6 address "::", port 5432
docmost-db-1       | 2024-07-29 11:34:22.814 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
docmost-db-1       | 2024-07-29 11:34:22.831 UTC [57] LOG:  database system was shut down at 2024-07-29 11:34:22 UTC
docmost-db-1       | 2024-07-29 11:34:22.845 UTC [1] LOG:  database system is ready to accept connections
docmost-docmost-1  |
docmost-docmost-1  | > server@0.2.8 start:prod /app/apps/server
docmost-docmost-1  | > cross-env NODE_ENV=production node dist/main
docmost-docmost-1  |

Once running

Attaching to docmost-db-1, docmost-docmost-1, docmost-redis-1
docmost-redis-1    | 1:C 29 Jul 2024 11:36:44.429 * oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
docmost-redis-1    | 1:C 29 Jul 2024 11:36:44.429 * Redis version=7.2.5, bits=64, commit=00000000, modified=0, pid=1, just started
docmost-redis-1    | 1:C 29 Jul 2024 11:36:44.429 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
docmost-redis-1    | 1:M 29 Jul 2024 11:36:44.429 * monotonic clock: POSIX clock_gettime
docmost-redis-1    | 1:M 29 Jul 2024 11:36:44.431 * Running mode=standalone, port=6379.
docmost-redis-1    | 1:M 29 Jul 2024 11:36:44.432 * Server initialized
docmost-redis-1    | 1:M 29 Jul 2024 11:36:44.433 * Loading RDB produced by version 7.2.5
docmost-redis-1    | 1:M 29 Jul 2024 11:36:44.433 * RDB age 41 seconds
docmost-redis-1    | 1:M 29 Jul 2024 11:36:44.433 * RDB memory usage when created 0.83 Mb
docmost-redis-1    | 1:M 29 Jul 2024 11:36:44.433 * Done loading RDB, keys loaded: 0, keys expired: 0.
docmost-redis-1    | 1:M 29 Jul 2024 11:36:44.433 * DB loaded from disk: 0.002 seconds
docmost-redis-1    | 1:M 29 Jul 2024 11:36:44.433 * Ready to accept connections tcp
docmost-db-1       |
docmost-db-1       | PostgreSQL Database directory appears to contain a database; Skipping initialization
docmost-db-1       |
docmost-db-1       | 2024-07-29 11:36:44.613 UTC [1] LOG:  starting PostgreSQL 16.3 on x86_64-pc-linux-musl, compiled by gcc (Alpine 13.2.1_git20240309) 13.2.1 20240309, 64-bit
docmost-db-1       | 2024-07-29 11:36:44.613 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
docmost-db-1       | 2024-07-29 11:36:44.613 UTC [1] LOG:  listening on IPv6 address "::", port 5432
docmost-db-1       | 2024-07-29 11:36:44.641 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
docmost-db-1       | 2024-07-29 11:36:44.659 UTC [29] LOG:  database system was shut down at 2024-07-29 11:36:04 UTC
docmost-db-1       | 2024-07-29 11:36:44.677 UTC [1] LOG:  database system is ready to accept connections
docmost-docmost-1  |
docmost-docmost-1  | > docmost@0.2.8 start /app
docmost-docmost-1  | > pnpm --filter ./apps/server run start:prod
docmost-docmost-1  |
docmost-docmost-1  |
docmost-docmost-1  | > server@0.2.8 start:prod /app/apps/server
docmost-docmost-1  | > cross-env NODE_ENV=production node dist/main
docmost-docmost-1  |
docmost-docmost-1  | (node:41) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
docmost-docmost-1  | (Use `node --trace-deprecation ...` to show where the warning was created)
docmost-docmost-1  | [Nest] 41  - 07/29/2024, 11:36:53 AM     LOG [NestFactory] Starting Nest application...
docmost-docmost-1  | [Nest] 41  - 07/29/2024, 11:36:53 AM     LOG [DatabaseModule] Establishing database connection
docmost-docmost-1  | [Nest] 41  - 07/29/2024, 11:36:53 AM     LOG [DatabaseModule] Database connection successful
docmost-docmost-1  | [Nest] 41  - 07/29/2024, 11:36:53 AM     LOG [DatabaseMigrationService] Migration "20240324T085400-uuid_v7_fn" executed successfully
docmost-docmost-1  | [Nest] 41  - 07/29/2024, 11:36:53 AM     LOG [DatabaseMigrationService] Migration "20240324T085500-workspaces" executed successfully
docmost-docmost-1  | [Nest] 41  - 07/29/2024, 11:36:53 AM     LOG [DatabaseMigrationService] Migration "20240324T085600-users" executed successfully
docmost-docmost-1  | [Nest] 41  - 07/29/2024, 11:36:53 AM     LOG [DatabaseMigrationService] Migration "20240324T085700-groups" executed successfully
docmost-docmost-1  | [Nest] 41  - 07/29/2024, 11:36:53 AM     LOG [DatabaseMigrationService] Migration "20240324T085900-spaces" executed successfully
docmost-docmost-1  | [Nest] 41  - 07/29/2024, 11:36:53 AM     LOG [DatabaseMigrationService] Migration "20240324T086100-add-workspace-fk" executed successfully
docmost-docmost-1  | [Nest] 41  - 07/29/2024, 11:36:53 AM     LOG [DatabaseMigrationService] Migration "20240324T086200-workspace_invitations" executed successfully
docmost-docmost-1  | [Nest] 41  - 07/29/2024, 11:36:53 AM     LOG [DatabaseMigrationService] Migration "20240324T086300-pages" executed successfully
docmost-docmost-1  | [Nest] 41  - 07/29/2024, 11:36:53 AM     LOG [DatabaseMigrationService] Migration "20240324T086400-page_history" executed successfully
docmost-docmost-1  | [Nest] 41  - 07/29/2024, 11:36:53 AM     LOG [DatabaseMigrationService] Migration "20240324T086600-comments" executed successfully
docmost-docmost-1  | [Nest] 41  - 07/29/2024, 11:36:53 AM     LOG [DatabaseMigrationService] Migration "20240324T086700-attachments" executed successfully
docmost-docmost-1  | [Nest] 41  - 07/29/2024, 11:36:53 AM     LOG [DatabaseMigrationService] Migration "20240324T086800-pages-tsvector-trigger" executed successfully
docmost-docmost-1  | [Nest] 41  - 07/29/2024, 11:36:53 AM     LOG [DatabaseMigrationService] Migration "20240707T145623-drop-redundant-pages-slug_id-index" executed successfully
docmost-docmost-1  | [Nest] 41  - 07/29/2024, 11:36:53 AM     LOG [NestApplication] Nest application successfully started

I could view the register page:

/content/images/2024/08/docmost-01.png

I setup a Freshbrewed workspace there and was then directed to a landing page

/content/images/2024/08/docmost-02.png

If I click on General, we can see the General site

/content/images/2024/08/docmost-03.png

I noticed things like Headings showed up immediately but inline Tables didn’t

/content/images/2024/08/docmost-04.png

A right-click will show formatting options, but noticeably table is absent

/content/images/2024/08/docmost-05.png

I’ll try importing a page to see if that solves my need (spaces added to backticks so you can see it here)

builder@DESKTOP-QADGF36:~$ vi /mnt/c/Users/isaac/Documents/test.markdown
builder@DESKTOP-QADGF36:~$ cat /mnt/c/Users/isaac/Documents/test.markdown
# A Markdown to Import

| th1 | th2 |
| --- | --- |
| td1 | td2 |

_some italices_

` ` `mermaidjs
pie title What Voldemort doesn't have?
         "FRIENDS" : 2
         "FAMILY" : 3
         "NOSE" : 45
` ` `

/content/images/2024/08/docmost-06.png

Now I can import from the ‘…’ menu

/content/images/2024/08/docmost-07.png

and choose Markdown

/content/images/2024/08/docmost-08.png

But I got an error

/content/images/2024/08/docmost-09.png

Let me try HTML

builder@DESKTOP-QADGF36:~$ vi /mnt/c/Users/isaac/Documents/test.html
builder@DESKTOP-QADGF36:~$ cat /mnt/c/Users/isaac/Documents/test.html 
<HTML>
        <BODY>
                <TABLE>
                        <TR><TH>TH1</TH><TH>TH2</TH></TR>
                        <TR><TD>TD1</TD><TD>TD2</TD></TR>
                </TABLE>
        </BODY>
</HTML>

That seemed to work just fine

/content/images/2024/08/docmost-10.png

I can even add rows and columns so it would be usable

/content/images/2024/08/docmost-12.png

I tried importing a static form HTML I had from our AWX post a couple weeks ago, but it doesn’t look very good

/content/images/2024/08/docmost-11.png

Search seems to work just fine as well

/content/images/2024/08/docmost-13.png

Login

After we have created our instance, we are only prompted for our login when visiting the URL

/content/images/2024/08/docmost-14.png

If we want to invite new members, we will have to setup SMTP

/content/images/2024/08/docmost-15.png

To do that, I actually noted the syntax from a MariusHosting post

builder@builder-T100:~/docmost$ git diff docker-compose.yml
diff --git a/docker-compose.yml b/docker-compose.yml
index f7fbc60..ad9e5f9 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -7,12 +7,19 @@ services:
       - db
       - redis
     environment:
-      APP_URL: 'http://localhost:3000'
-      APP_SECRET: 'REPLACE_WITH_LONG_SECRET'
-      DATABASE_URL: 'postgresql://docmost:STRONG_DB_PASSWORD@db:5432/docmost?schema=public'
+      APP_URL: 'http://localhost:3220'
+      APP_SECRET: '0a447e91bb8e1155cf579abf9d7dd2ee9932cc03'
+      DATABASE_URL: 'postgresql://docmost:D0cm0st4FunNPr0fit_2024@db:5432/docmost?schema=public'
       REDIS_URL: 'redis://redis:6379'
+      MAIL_DRIVER: smtp
+      SMTP_HOST: smtp.sendgrid.net
+      SMTP_PORT: 465
+      SMTP_USERNAME: apikey
+      SMTP_PASSWORD: SG.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+      MAIL_FROM_ADDRESS: isaac@freshbrewed.science
+      MAIL_FROM_NAME: Docmost
     ports:
-      - "3000:3000"
+      - "3220:3000"
     restart: unless-stopped
     volumes:
       - docmost:/app/data/storage
@@ -22,7 +29,7 @@ services:
     environment:
       POSTGRES_DB: docmost
       POSTGRES_USER: docmost
-      POSTGRES_PASSWORD: STRONG_DB_PASSWORD
+      POSTGRES_PASSWORD: D0cm0st4FunNPr0fit_2024
     restart: unless-stopped
     volumes:
       - db_data:/var/lib/postgresql/data
builder@builder-T100:~/docmost$

I’ll then start it up

builder@builder-T100:~/docmost$ docker compose up
[+] Building 0.0s (0/0)
[+] Running 3/3
 ✔ Container docmost-db-1       Created                                                                                                                                                                                                                                                              0.0s
 ✔ Container docmost-redis-1    Created                                                                                                                                                                                                                                                              0.0s
 ✔ Container docmost-docmost-1  Recreated                                                                                                                                                                                                                                                            0.1s
Attaching to docmost-db-1, docmost-docmost-1, docmost-redis-1
docmost-redis-1    | 1:C 29 Jul 2024 12:00:45.007 * oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
docmost-redis-1    | 1:C 29 Jul 2024 12:00:45.007 * Redis version=7.2.5, bits=64, commit=00000000, modified=0, pid=1, just started
docmost-redis-1    | 1:C 29 Jul 2024 12:00:45.007 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
docmost-redis-1    | 1:M 29 Jul 2024 12:00:45.008 * monotonic clock: POSIX clock_gettime
docmost-redis-1    | 1:M 29 Jul 2024 12:00:45.010 * Running mode=standalone, port=6379.
docmost-redis-1    | 1:M 29 Jul 2024 12:00:45.010 * Server initialized
docmost-redis-1    | 1:M 29 Jul 2024 12:00:45.012 * Loading RDB produced by version 7.2.5
docmost-redis-1    | 1:M 29 Jul 2024 12:00:45.012 * RDB age 180 seconds
docmost-redis-1    | 1:M 29 Jul 2024 12:00:45.012 * RDB memory usage when created 1.48 Mb
docmost-redis-1    | 1:M 29 Jul 2024 12:00:45.012 * Done loading RDB, keys loaded: 1, keys expired: 1.
docmost-redis-1    | 1:M 29 Jul 2024 12:00:45.012 * DB loaded from disk: 0.002 seconds
docmost-redis-1    | 1:M 29 Jul 2024 12:00:45.012 * Ready to accept connections tcp
docmost-db-1       |
docmost-db-1       | PostgreSQL Database directory appears to contain a database; Skipping initialization
docmost-db-1       |
docmost-db-1       | 2024-07-29 12:00:45.149 UTC [1] LOG:  starting PostgreSQL 16.3 on x86_64-pc-linux-musl, compiled by gcc (Alpine 13.2.1_git20240309) 13.2.1 20240309, 64-bit
docmost-db-1       | 2024-07-29 12:00:45.149 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
docmost-db-1       | 2024-07-29 12:00:45.150 UTC [1] LOG:  listening on IPv6 address "::", port 5432
docmost-db-1       | 2024-07-29 12:00:45.162 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
docmost-db-1       | 2024-07-29 12:00:45.180 UTC [28] LOG:  database system was shut down at 2024-07-29 11:57:45 UTC
docmost-db-1       | 2024-07-29 12:00:45.203 UTC [1] LOG:  database system is ready to accept connections
docmost-docmost-1  |
docmost-docmost-1  | > docmost@0.2.8 start /app
docmost-docmost-1  | > pnpm --filter ./apps/server run start:prod
docmost-docmost-1  |
docmost-docmost-1  |
docmost-docmost-1  | > server@0.2.8 start:prod /app/apps/server
docmost-docmost-1  | > cross-env NODE_ENV=production node dist/main
docmost-docmost-1  |
docmost-docmost-1  | (node:40) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
docmost-docmost-1  | (Use `node --trace-deprecation ...` to show where the warning was created)
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:00:54 PM     LOG [NestFactory] Starting Nest application...
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:00:54 PM     LOG [DatabaseModule] Establishing database connection
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:00:54 PM     LOG [DatabaseModule] Database connection successful
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:00:54 PM     LOG [DatabaseMigrationService] No pending database migrations
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:00:54 PM     LOG [NestApplication] Nest application successfully started

Now I’ll try and invite a user by email

/content/images/2024/08/docmost-16.png

I see errors in the logs


docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:00:54 PM     LOG [NestApplication] Nest application successfully started
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:02:35 PM   ERROR [EmailProcessor] Error processing send-email job. Reason: Greeting never received
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:03:15 PM   ERROR [EmailProcessor] Error processing send-email job. Reason: Greeting never received
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:04:06 PM   ERROR [EmailProcessor] Error processing send-email job. Reason: Greeting never received

I’m worried this is a setting that must exist at setup.

I’ll start fresh again

builder@builder-T100:~/docmost$ docker compose rm
? Going to remove docmost-docmost-1, docmost-db-1, docmost-redis-1 Yes
[+] Removing 3/3
 ✔ Container docmost-redis-1    Removed                                                                                                                                                                                                                                                              0.1s
 ✔ Container docmost-docmost-1  Removed                                                                                                                                                                                                                                                              0.1s
 ✔ Container docmost-db-1       Removed                                                                                                                                                                                                                                                              0.1s
builder@builder-T100:~/docmost$ docker compose up
[+] Building 0.0s (0/0)
[+] Running 3/3
 ✔ Container docmost-redis-1    Created                                                                                                                                                                                                                                                              0.2s
 ✔ Container docmost-db-1       Created                                                                                                                                                                                                                                                              0.2s
 ✔ Container docmost-docmost-1  Created                                                                                                                                                                                                                                                              0.1s
Attaching to docmost-db-1, docmost-docmost-1, docmost-redis-1
docmost-redis-1    | 1:C 29 Jul 2024 12:05:52.611 * oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
... snip ...

I had to stop and do it again but with new volume names to make it start over

builder@builder-T100:~/docmost$ git diff docker-compose.yml
diff --git a/docker-compose.yml b/docker-compose.yml
index f7fbc60..06187ef 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -7,33 +7,40 @@ services:
       - db
       - redis
     environment:
-      APP_URL: 'http://localhost:3000'
-      APP_SECRET: 'REPLACE_WITH_LONG_SECRET'
-      DATABASE_URL: 'postgresql://docmost:STRONG_DB_PASSWORD@db:5432/docmost?schema=public'
+      APP_URL: 'http://localhost:3220'
+      APP_SECRET: '0a447e91bb8e1155cf579abf9d7dd2ee9932cc03'
+      DATABASE_URL: 'postgresql://docmost:D0cm0st4FunNPr0fit_2024@db:5432/docmost?schema=public'
       REDIS_URL: 'redis://redis:6379'
+      MAIL_DRIVER: smtp
+      SMTP_HOST: smtp.sendgrid.net
+      SMTP_PORT: 465
+      SMTP_USERNAME: apikey
+      SMTP_PASSWORD: SG.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+      MAIL_FROM_ADDRESS: isaac@freshbrewed.science
+      MAIL_FROM_NAME: Docmost
     ports:
-      - "3000:3000"
+      - "3220:3000"
     restart: unless-stopped
     volumes:
-      - docmost:/app/data/storage
+      - docmost2:/app/data/storage

   db:
     image: postgres:16-alpine
     environment:
       POSTGRES_DB: docmost
       POSTGRES_USER: docmost
-      POSTGRES_PASSWORD: STRONG_DB_PASSWORD
+      POSTGRES_PASSWORD: D0cm0st4FunNPr0fit_2024
     restart: unless-stopped
     volumes:
-      - db_data:/var/lib/postgresql/data
+      - db_data2:/var/lib/postgresql/data

   redis:
     image: redis:7.2-alpine
     restart: unless-stopped
     volumes:
-      - redis_data:/data
+      - redis_data2:/data

 volumes:
-  docmost:
-  db_data:
-  redis_data:
+  docmost2:
+  db_data2:
+  redis_data2:

Then start it fresh

builder@builder-T100:~/docmost$ docker compose up
[+] Building 0.0s (0/0)
[+] Running 6/6
 ✔ Volume "docmost_docmost2"     Created                                                                                                                                                                                                                                                             0.0s
 ✔ Volume "docmost_db_data2"     Created                                                                                                                                                                                                                                                             0.0s
 ✔ Volume "docmost_redis_data2"  Created                                                                                                                                                                                                                                                             0.0s
 ✔ Container docmost-redis-1     Created                                                                                                                                                                                                                                                             0.1s
 ✔ Container docmost-db-1        Created                                                                                                                                                                                                                                                             0.2s
 ✔ Container docmost-docmost-1   Created                                                                                                                                                                                                                                                             0.1s
Attaching to docmost-db-1, docmost-docmost-1, docmost-redis-1
docmost-redis-1    | 1:C 29 Jul 2024 12:07:39.904 * oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
docmost-redis-1    | 1:C 29 Jul 2024 12:07:39.904 * Redis version=7.2.5, bits=64, commit=00000000, modified=0, pid=1, just started
docmost-redis-1    | 1:C 29 Jul 2024 12:07:39.904 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
docmost-redis-1    | 1:M 29 Jul 2024 12:07:39.905 * monotonic clock: POSIX clock_gettime
docmost-redis-1    | 1:M 29 Jul 2024 12:07:39.907 * Running mode=standalone, port=6379.
docmost-redis-1    | 1:M 29 Jul 2024 12:07:39.907 * Server initialized
docmost-redis-1    | 1:M 29 Jul 2024 12:07:39.907 * Ready to accept connections tcp
docmost-db-1       | The files belonging to this database system will be owned by user "postgres".
docmost-db-1       | This user must also own the server process.
docmost-db-1       |
docmost-db-1       | The database cluster will be initialized with locale "en_US.utf8".
docmost-db-1       | The default database encoding has accordingly been set to "UTF8".
docmost-db-1       | The default text search configuration will be set to "english".
docmost-db-1       |
docmost-db-1       | Data page checksums are disabled.
docmost-db-1       |
docmost-db-1       | fixing permissions on existing directory /var/lib/postgresql/data ... ok
docmost-db-1       | creating subdirectories ... ok
docmost-db-1       | selecting dynamic shared memory implementation ... posix
docmost-db-1       | selecting default max_connections ... 100
docmost-db-1       | selecting default shared_buffers ... 128MB
docmost-db-1       | selecting default time zone ... UTC
docmost-db-1       | creating configuration files ... ok
docmost-db-1       | running bootstrap script ... ok
docmost-db-1       | sh: locale: not found
docmost-db-1       | 2024-07-29 12:07:40.643 UTC [35] WARNING:  no usable system locales were found
docmost-db-1       | performing post-bootstrap initialization ... ok
docmost-docmost-1  |
docmost-docmost-1  | > docmost@0.2.8 start /app
docmost-docmost-1  | > pnpm --filter ./apps/server run start:prod
docmost-docmost-1  |
docmost-db-1       | initdb: warning: enabling "trust" authentication for local connections
docmost-db-1       | initdb: hint: You can change this by editing pg_hba.conf or using the option -A, or --auth-local and --auth-host, the next time you run initdb.
docmost-db-1       | syncing data to disk ... ok
docmost-db-1       |
docmost-db-1       |
docmost-db-1       | Success. You can now start the database server using:
docmost-db-1       |
docmost-db-1       |     pg_ctl -D /var/lib/postgresql/data -l logfile start
docmost-db-1       |
docmost-db-1       | waiting for server to start....2024-07-29 12:07:41.522 UTC [41] LOG:  starting PostgreSQL 16.3 on x86_64-pc-linux-musl, compiled by gcc (Alpine 13.2.1_git20240309) 13.2.1 20240309, 64-bit
docmost-db-1       | 2024-07-29 12:07:41.533 UTC [41] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
docmost-db-1       | 2024-07-29 12:07:41.541 UTC [44] LOG:  database system was shut down at 2024-07-29 12:07:41 UTC
docmost-db-1       | 2024-07-29 12:07:41.549 UTC [41] LOG:  database system is ready to accept connections
docmost-db-1       |  done
docmost-db-1       | server started
docmost-db-1       | CREATE DATABASE
docmost-db-1       |
docmost-db-1       |
docmost-db-1       | /usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
docmost-db-1       |
docmost-db-1       | 2024-07-29 12:07:41.807 UTC [41] LOG:  received fast shutdown request
docmost-db-1       | waiting for server to shut down....2024-07-29 12:07:41.809 UTC [41] LOG:  aborting any active transactions
docmost-db-1       | 2024-07-29 12:07:41.816 UTC [41] LOG:  background worker "logical replication launcher" (PID 47) exited with exit code 1
docmost-db-1       | 2024-07-29 12:07:41.816 UTC [42] LOG:  shutting down
docmost-db-1       | 2024-07-29 12:07:41.823 UTC [42] LOG:  checkpoint starting: shutdown immediate
docmost-db-1       | 2024-07-29 12:07:41.891 UTC [42] LOG:  checkpoint complete: wrote 924 buffers (5.6%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.051 s, sync=0.013 s, total=0.076 s; sync files=301, longest=0.002 s, average=0.001 s; distance=4267 kB, estimate=4267 kB; lsn=0/191AA98, redo lsn=0/191AA98
docmost-db-1       | 2024-07-29 12:07:41.898 UTC [41] LOG:  database system is shut down
docmost-db-1       |  done
docmost-db-1       | server stopped
docmost-db-1       |
docmost-db-1       | PostgreSQL init process complete; ready for start up.
docmost-db-1       |
docmost-db-1       | 2024-07-29 12:07:41.939 UTC [1] LOG:  starting PostgreSQL 16.3 on x86_64-pc-linux-musl, compiled by gcc (Alpine 13.2.1_git20240309) 13.2.1 20240309, 64-bit
docmost-db-1       | 2024-07-29 12:07:41.939 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
docmost-db-1       | 2024-07-29 12:07:41.939 UTC [1] LOG:  listening on IPv6 address "::", port 5432
docmost-db-1       | 2024-07-29 12:07:41.946 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
docmost-db-1       | 2024-07-29 12:07:41.952 UTC [57] LOG:  database system was shut down at 2024-07-29 12:07:41 UTC
docmost-db-1       | 2024-07-29 12:07:41.959 UTC [1] LOG:  database system is ready to accept connections
docmost-docmost-1  |
docmost-docmost-1  | > server@0.2.8 start:prod /app/apps/server
docmost-docmost-1  | > cross-env NODE_ENV=production node dist/main
docmost-docmost-1  |
docmost-docmost-1  | (node:40) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
docmost-docmost-1  | (Use `node --trace-deprecation ...` to show where the warning was created)
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:07:58 PM     LOG [NestFactory] Starting Nest application...
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:07:58 PM     LOG [DatabaseModule] Establishing database connection
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:07:58 PM     LOG [DatabaseModule] Database connection successful
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:07:58 PM     LOG [DatabaseMigrationService] Migration "20240324T085400-uuid_v7_fn" executed successfully
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:07:58 PM     LOG [DatabaseMigrationService] Migration "20240324T085500-workspaces" executed successfully
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:07:58 PM     LOG [DatabaseMigrationService] Migration "20240324T085600-users" executed successfully
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:07:58 PM     LOG [DatabaseMigrationService] Migration "20240324T085700-groups" executed successfully
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:07:58 PM     LOG [DatabaseMigrationService] Migration "20240324T085900-spaces" executed successfully
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:07:58 PM     LOG [DatabaseMigrationService] Migration "20240324T086100-add-workspace-fk" executed successfully
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:07:58 PM     LOG [DatabaseMigrationService] Migration "20240324T086200-workspace_invitations" executed successfully
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:07:58 PM     LOG [DatabaseMigrationService] Migration "20240324T086300-pages" executed successfully
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:07:58 PM     LOG [DatabaseMigrationService] Migration "20240324T086400-page_history" executed successfully
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:07:58 PM     LOG [DatabaseMigrationService] Migration "20240324T086600-comments" executed successfully
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:07:58 PM     LOG [DatabaseMigrationService] Migration "20240324T086700-attachments" executed successfully
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:07:58 PM     LOG [DatabaseMigrationService] Migration "20240324T086800-pages-tsvector-trigger" executed successfully
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:07:58 PM     LOG [DatabaseMigrationService] Migration "20240707T145623-drop-redundant-pages-slug_id-index" executed successfully
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:07:58 PM     LOG [NestApplication] Nest application successfully started

Still no go

docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:07:58 PM     LOG [NestApplication] Nest application successfully started
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:09:36 PM   ERROR [EmailProcessor] Error processing send-email job. Reason: Greeting never received
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:10:17 PM   ERROR [EmailProcessor] Error processing send-email job. Reason: Greeting never received
docmost-docmost-1  | [Nest] 40  - 07/29/2024, 12:11:07 PM   ERROR [EmailProcessor] Error processing send-email job. Reason: Greeting never received

I tried switching from the SSL port to the TLS one

SMTP_PORT: 587

That worked!

/content/images/2024/08/docmost-17.png

Now that worked, but the email gives a ‘localhost’ URL so we’ll just translate to our Dockerhost IP

/content/images/2024/08/docmost-18.png

Now I have a second user

/content/images/2024/08/docmost-19.png

Production

We first need a DNS name so I’ll create an A Record in Azure DNS for docmost.tpk.pw

$ az account set --subscription "Pay-As-You-Go" && az network dns record-set a add-record -g idjdnsrg -z tpk.pw -a 75.73.224.240 -n docmost
{
  "ARecords": [
    {
      "ipv4Address": "75.73.224.240"
    }
  ],
  "TTL": 3600,
  "etag": "41fd5e64-f700-4997-9cd8-2fa3f7aea81f",
  "fqdn": "docmost.tpk.pw.",
  "id": "/subscriptions/d955c0ba-13dc-44cf-a29a-8fed74cbb22d/resourceGroups/idjdnsrg/providers/Microsoft.Network/dnszones/tpk.pw/A/docmost",
  "name": "docmost",
  "provisioningState": "Succeeded",
  "resourceGroup": "idjdnsrg",
  "targetResource": {},
  "type": "Microsoft.Network/dnszones/A"
}

I’ll need a namespace with Redis and PostgreSQL setup.

First, let me install Redis

builder@DESKTOP-QADGF36:~/Workspaces/docmost$ kubectl create ns docmost
namespace/docmost created
builder@DESKTOP-QADGF36:~/Workspaces/docmost$ helm install redis bitnami/redis --namespace docmost --set auth.enabled=false
NAME: redis
LAST DEPLOYED: Mon Jul 29 07:36:38 2024
NAMESPACE: docmost
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: redis
CHART VERSION: 19.6.1
APP VERSION: 7.2.5

** Please be patient while the chart is being deployed **

Redis&reg; can be accessed on the following DNS names from within your cluster:

    redis-master.docmost.svc.cluster.local for read/write operations (port 6379)
    redis-replicas.docmost.svc.cluster.local for read-only operations (port 6379)



To connect to your Redis&reg; server:

1. Run a Redis&reg; pod that you can use as a client:

   kubectl run --namespace docmost redis-client --restart='Never'  --image docker.io/bitnami/redis:7.2.5-debian-12-r2 --command -- sleep infinity

   Use the following command to attach to the pod:

   kubectl exec --tty -i redis-client \
   --namespace docmost -- bash

2. Connect using the Redis&reg; CLI:
   redis-cli -h redis-master
   redis-cli -h redis-replicas

To connect to your database from outside the cluster execute the following commands:

    kubectl port-forward --namespace docmost svc/redis-master 6379:6379 &
    redis-cli -h 127.0.0.1 -p 6379

WARNING: There are "resources" sections in the chart not set. Using "resourcesPreset" is not recommended for production. For production installations, please set the following values according to your workload needs:
  - replica.resources
  - master.resources
+info https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/

Then add PostgreSQL

$ helm install postgresql bitnami/postgresql --namespace docmost \
  --set postgresqlUsername=docmost \
  --set postgresqlPassword=D0cm0st4FunNPr0fit_2024 \
  --set postgresqlDatabase=docmost

Soon I had both Redis and PostgreSQL running

$ kubectl get pods -n docmost
NAME               READY   STATUS    RESTARTS   AGE
redis-master-0     1/1     Running   0          2m47s
redis-replicas-0   1/1     Running   0          2m47s
redis-replicas-1   1/1     Running   0          2m10s
redis-replicas-2   1/1     Running   0          98s
postgresql-0       1/1     Running   0          25s

I’ll now try installing with a helm chart I built out

$ helm install -n docmost docmost ./docmost/
NAME: docmost
LAST DEPLOYED: Mon Jul 29 07:45:56 2024
NAMESPACE: docmost
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
  https://docmost.tpk.pw/

I can see it starting

builder@DESKTOP-QADGF36:~/Workspaces/docmost$ kubectl get pods -n docmost
NAME                       READY   STATUS              RESTARTS   AGE
redis-master-0             1/1     Running             0          14m
redis-replicas-0           1/1     Running             0          14m
redis-replicas-1           1/1     Running             0          13m
redis-replicas-2           1/1     Running             0          13m
postgresql-0               1/1     Running             0          11m
docmost-6f6f5fb87b-wkwnt   0/1     ContainerCreating   0          12s
builder@DESKTOP-QADGF36:~/Workspaces/docmost$ kubectl get ingress -n docmost
NAME      CLASS    HOSTS            ADDRESS   PORTS     AGE
docmost   <none>   docmost.tpk.pw             80, 443   20s
builder@DESKTOP-QADGF36:~/Workspaces/docmost$ kubectl get cert -n docmost
NAME           READY   SECRET         AGE
docmoste-tls   False   docmoste-tls   24s
builder@DESKTOP-QADGF36:~/Workspaces/docmost$ kubectl get pvc -n docmost
NAME                          STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
redis-data-redis-replicas-0   Bound    pvc-75da81e7-2376-4b83-a621-4e7e1d0fd2dc   8Gi        RWO            local-path     14m
redis-data-redis-master-0     Bound    pvc-95264dc0-f16e-4c6c-81e4-02c85cfd3a43   8Gi        RWO            local-path     14m
redis-data-redis-replicas-1   Bound    pvc-0f32f46d-9ee3-4247-bc41-d4ad5330c0a4   8Gi        RWO            local-path     14m
redis-data-redis-replicas-2   Bound    pvc-4c69f06c-d3c0-46c3-87c8-fb4120789904   8Gi        RWO            local-path     13m
data-postgresql-0             Bound    pvc-8e76d6f9-39ac-48dc-ae30-efb3a39c0422   8Gi        RWO            local-path     12m
docmost-pvc                   Bound    pvc-ade0cfdc-6fc9-402b-88ae-09b88db4a22e   1Gi        RWO            local-path     48s

I could see cert get created

$ kubectl get cert -n docmost
NAME           READY   SECRET         AGE
docmoste-tls   True    docmoste-tls   81s

I found the database did not create as I hoped.

builder@DESKTOP-QADGF36:~/Workspaces/docmost$ kubectl logs docmost-6f6f5fb87b-wkwnt -n docmost

> docmost@0.2.8 start /app
> pnpm --filter ./apps/server run start:prod


> server@0.2.8 start:prod /app/apps/server
> cross-env NODE_ENV=production node dist/main

(node:42) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
[Nest] 42  - 07/29/2024, 12:58:14 PM     LOG [NestFactory] Starting Nest application...
[Nest] 42  - 07/29/2024, 12:58:15 PM     LOG [DatabaseModule] Establishing database connection
[Nest] 42  - 07/29/2024, 12:58:15 PM   ERROR [DatabaseModule] error: password authentication failed for user "docmost"
[Nest] 42  - 07/29/2024, 12:58:15 PM     LOG [DatabaseModule] Retrying [1/15] in 3 seconds
[Nest] 42  - 07/29/2024, 12:58:18 PM   ERROR [DatabaseModule] error: password authentication failed for user "docmost"
[Nest] 42  - 07/29/2024, 12:58:18 PM     LOG [DatabaseModule] Retrying [2/15] in 3 seconds
[Nest] 42  - 07/29/2024, 12:58:21 PM   ERROR [DatabaseModule] error: password authentication failed for user "docmost"
[Nest] 42  - 07/29/2024, 12:58:21 PM     LOG [DatabaseModule] Retrying [3/15] in 3 seconds
[Nest] 42  - 07/29/2024, 12:58:24 PM   ERROR [DatabaseModule] error: password authentication failed for user "docmost"
[Nest] 42  - 07/29/2024, 12:58:24 PM     LOG [DatabaseModule] Retrying [4/15] in 3 seconds
[Nest] 42  - 07/29/2024, 12:58:27 PM   ERROR [DatabaseModule] error: password authentication failed for user "docmost"
[Nest] 42  - 07/29/2024, 12:58:27 PM     LOG [DatabaseModule] Retrying [5/15] in 3 seconds
[Nest] 42  - 07/29/2024, 12:58:30 PM   ERROR [DatabaseModule] error: password authentication failed for user "docmost"
[Nest] 42  - 07/29/2024, 12:58:30 PM     LOG [DatabaseModule] Retrying [6/15] in 3 seconds
[Nest] 42  - 07/29/2024, 12:58:33 PM   ERROR [DatabaseModule] error: password authentication failed for user "docmost"
[Nest] 42  - 07/29/2024, 12:58:33 PM     LOG [DatabaseModule] Retrying [7/15] in 3 seconds
/app/apps/server:
 ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL  server@0.2.8 start:prod: `cross-env NODE_ENV=production node dist/main`
Exit status 1
 ELIFECYCLE  Command failed with exit code 1.

I had to use an ubuntu pod to conect as postgres user and create the user and database

postgres=# CREATE DATABASE docmost;
CREATE DATABASE
postgres=# CREATE USER docmost WITH PASSWORD 'D0cm0st4FunNPr0fit_2024';
CREATE ROLE
postgres=# GRANT ALL PRIVILEGES ON DATABASE docmost TO docmost;
GRANT
postgres=# GRANT ALL ON SCHEMA public TO docmost;
GRANT
postgres=# GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO docmost;
GRANT
postgres=# GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO docmost;
GRANT
postgres=# exit

I’m a bit stumped as I even got explicit

root@my-shell:/# psql -U postgres -h postgresql -p 5432
psql (16.3 (Ubuntu 16.3-0ubuntu0.24.04.1))
Type "help" for help.

postgres=# GRANT ALL ON SCHEMA public FROM PUBLIC;
ERROR:  syntax error at or near "FROM"
LINE 1: GRANT ALL ON SCHEMA public FROM PUBLIC;
                                   ^
postgres=# GRANT USAGE ON SCHEMA public TO docmost;
GRANT
postgres=# GRANT ALL                            ON ALL TABLES IN SCHEMA public TO docmost;
GRANT

But I still see the error about permissions

builder@DESKTOP-QADGF36:~/Workspaces/docmost$ kubectl logs docmost-57f684ff6-gbh4q -n docmost

> docmost@0.2.8 start /app
> pnpm --filter ./apps/server run start:prod


> server@0.2.8 start:prod /app/apps/server
> cross-env NODE_ENV=production node dist/main

(node:41) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
[Nest] 41  - 07/29/2024, 1:14:20 PM     LOG [NestFactory] Starting Nest application...
[Nest] 41  - 07/29/2024, 1:14:21 PM     LOG [DatabaseModule] Establishing database connection
[Nest] 41  - 07/29/2024, 1:14:21 PM     LOG [DatabaseModule] Database connection successful
[Nest] 41  - 07/29/2024, 1:14:21 PM   ERROR [DatabaseMigrationService] Failed to run database migration. Exiting program.
[Nest] 41  - 07/29/2024, 1:14:21 PM   ERROR [DatabaseMigrationService] error: permission denied for schema public
/app/apps/server:
 ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL  server@0.2.8 start:prod: `cross-env NODE_ENV=production node dist/main`
Exit status 1
 ELIFECYCLE  Command failed with exit code 1.

I’ll admit I was fighting the credentials and PostgreSQL permissions for a while until, just to ensure I wasn’t nuts, I swapped for the postgres user (which has a password in a kubernetes secret) and that worked

builder@LuiGi:~/Workspaces/docmost$ kubectl logs docmost-574497bcf8-nmsdl -n docmost

> docmost@0.2.8 start /app
> pnpm --filter ./apps/server run start:prod


> server@0.2.8 start:prod /app/apps/server
> cross-env NODE_ENV=production node dist/main

(node:41) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
[Nest] 41  - 07/29/2024, 11:30:21 PM     LOG [NestFactory] Starting Nest application...
[Nest] 41  - 07/29/2024, 11:30:21 PM     LOG [DatabaseModule] Establishing database connection
[Nest] 41  - 07/29/2024, 11:30:21 PM     LOG [DatabaseModule] Database connection successful
[Nest] 41  - 07/29/2024, 11:30:21 PM     LOG [DatabaseMigrationService] Migration "20240324T085400-uuid_v7_fn" executed successfully
[Nest] 41  - 07/29/2024, 11:30:21 PM     LOG [DatabaseMigrationService] Migration "20240324T085500-workspaces" executed successfully
[Nest] 41  - 07/29/2024, 11:30:21 PM     LOG [DatabaseMigrationService] Migration "20240324T085600-users" executed successfully
[Nest] 41  - 07/29/2024, 11:30:21 PM     LOG [DatabaseMigrationService] Migration "20240324T085700-groups" executed successfully
[Nest] 41  - 07/29/2024, 11:30:21 PM     LOG [DatabaseMigrationService] Migration "20240324T085900-spaces" executed successfully
[Nest] 41  - 07/29/2024, 11:30:21 PM     LOG [DatabaseMigrationService] Migration "20240324T086100-add-workspace-fk" executed successfully
[Nest] 41  - 07/29/2024, 11:30:21 PM     LOG [DatabaseMigrationService] Migration "20240324T086200-workspace_invitations" executed successfully
[Nest] 41  - 07/29/2024, 11:30:21 PM     LOG [DatabaseMigrationService] Migration "20240324T086300-pages" executed successfully
[Nest] 41  - 07/29/2024, 11:30:21 PM     LOG [DatabaseMigrationService] Migration "20240324T086400-page_history" executed successfully
[Nest] 41  - 07/29/2024, 11:30:21 PM     LOG [DatabaseMigrationService] Migration "20240324T086600-comments" executed successfully
[Nest] 41  - 07/29/2024, 11:30:21 PM     LOG [DatabaseMigrationService] Migration "20240324T086700-attachments" executed successfully
[Nest] 41  - 07/29/2024, 11:30:21 PM     LOG [DatabaseMigrationService] Migration "20240324T086800-pages-tsvector-trigger" executed successfully
[Nest] 41  - 07/29/2024, 11:30:21 PM     LOG [DatabaseMigrationService] Migration "20240707T145623-drop-redundant-pages-slug_id-index" executed successfully
[Nest] 41  - 07/29/2024, 11:30:21 PM     LOG [NestApplication] Nest application successfully started

I can now setup my site using the wizard

/content/images/2024/08/docmost-20.png

I’ll then try inviting a member (to verify email)

/content/images/2024/08/docmost-21.png

I then got an email in Outlook

/content/images/2024/08/docmost-22.jpg

which let me signup

/content/images/2024/08/docmost-23.jpg

and I can see I’m now in the project

/content/images/2024/08/docmost-24.jpg

It was in testing the Kubernetes instance I realized that there is a way in the editor to just add a table inline (not using Markdown). One uses the /table command

/content/images/2024/08/docmost-25.png

Which creates a quick 3x3 table you can then modify

/content/images/2024/08/docmost-26.png

Cachet

This app has a Docker Compose as well:

version: "3"

services:
  postgres:
    image: postgres:12-alpine
    volumes:
      - /var/lib/postgresql/data
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
    restart: always
  cachet:
    build:
      context: .
      args:
        - cachet_ver=2.4
    ports:
      - 80:8000
    links:
      - postgres:postgres
    environment:
      - DB_DRIVER=pgsql
      - DB_HOST=postgres
      - DB_PORT=5432
      - DB_DATABASE=postgres
      - DB_USERNAME=postgres
      - DB_PASSWORD=postgres
      - DB_PREFIX=chq_
      - APP_KEY=${APP_KEY:-null}
      - APP_LOG=errorlog
      - APP_ENV=${APP_ENV:-production}
      - APP_DEBUG=false
      - DEBUG=false
    depends_on:
      - postgres
    restart: on-failure

I’ll try and make a basic Kubernetes manifest YAML we could use to approximate that

$ cat manifest.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgres
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
      - name: postgres
        image: postgres:12-alpine
        env:
        - name: POSTGRES_USER
          value: postgres
        - name: POSTGRES_PASSWORD
          value: postgres
        volumeMounts:
        - mountPath: /var/lib/postgresql/data
          name: postgres-data
      volumes:
      - name: postgres-data
        persistentVolumeClaim:
          claimName: postgres-data
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: cachet
spec:
  replicas: 1
  selector:
    matchLabels:
      app: cachet
  template:
    metadata:
      labels:
        app: cachet
    spec:
      containers:
      - name: cachet
        image: cachet:2.4
        env:
        - name: DB_DRIVER
          value: pgsql
        - name: DB_HOST
          value: postgres
        - name: DB_PORT
          value: "5432"
        - name: DB_DATABASE
          value: postgres
        - name: DB_USERNAME
          value: postgres
        - name: DB_PASSWORD
          value: postgres
        - name: DB_PREFIX
          value: chq_
        - name: APP_KEY
          value: asdfsadfasdfsadfasdf
        - name: APP_LOG
          value: errorlog
        - name: APP_ENV
          value: production
        - name: APP_DEBUG
          value: "false"
        - name: DEBUG
          value: "false"
        ports:
        - containerPort: 8000
---
apiVersion: v1
kind: Service
metadata:
  name: cachet
spec:
  selector:
    app: cachet
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8000
---
apiVersion: v1
kind: Service
metadata:
  name: postgres
spec:
  selector:
    app: postgres
  ports:
    - protocol: TCP
      port: 5432
      targetPort: 5432
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-data
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi
  storageClassName: local-path

I can then create the namespace and apply it

builder@LuiGi:~/Workspaces/cachet$ kubectl create ns cachet
namespace/cachet created
builder@LuiGi:~/Workspaces/cachet$ kubectl apply -f ./manifest.yaml -n cachet
deployment.apps/postgres created
deployment.apps/cachet created
service/cachet created
service/postgres created
persistentvolumeclaim/postgres-data created

My first issue was the cachet pod was in an ImagePullBackOff failure

Events:
  Type     Reason     Age                      From               Message
  ----     ------     ----                     ----               -------
  Normal   Scheduled  69s                      default-scheduler  Successfully assigned cachet/cachet-74774554fd-g95nm to builder-hp-elitebook-850-g2
  Normal   BackOff    6s (x4 over 68s)         kubelet            Back-off pulling image "cachet:2.4"
  Warning  Failed     6s (x4 over 68s)         kubelet            Error: ImagePullBackOff
  Normal   Pulling    <invalid> (x4 over 69s)  kubelet            Pulling image "cachet:2.4"
  Warning  Failed     <invalid> (x4 over 68s)  kubelet            Failed to pull image "cachet:2.4": rpc error: code = Unknown desc = failed to pull and unpack image "docker.io/library/cachet:2.4": failed to resolve reference "docker.io/library/cachet:2.4": pull access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failed
  Warning  Failed     <invalid> (x4 over 68s)  kubelet            Error: ErrImagePull

I think the issue here is the mainline is slated for ‘2.4’ which is not released and thus not in Dockerhub under cachethq/docker

Let’s use the last release of 2.3.18.

I’ll switch that up in the manifest YAML

    spec:
      containers:
      - name: cachet
        image: cachethq/docker:2.3.18

and apply

builder@LuiGi:~/Workspaces/cachet$ kubectl apply -f ./manifest.yaml -n cachet
deployment.apps/postgres unchanged
deployment.apps/cachet configured
service/cachet unchanged
service/postgres unchanged
persistentvolumeclaim/postgres-data unchanged

Now I get a different error all-together

builder@LuiGi:~/Workspaces/cachet$ kubectl get pods -n cachet
NAME                        READY   STATUS             RESTARTS     AGE
postgres-79d66cd6dc-87l9n   1/1     Running            0            5m18s
cachet-74774554fd-g95nm     0/1     ImagePullBackOff   0            5m17s
cachet-5cdd8bf698-7prf2     0/1     CrashLoopBackOff   1 (8s ago)   20s
builder@LuiGi:~/Workspaces/cachet$ kubectl logs cachet-5cdd8bf698-7prf2 -n cachet
Initializing Cachet container ...
Attempting to connect to database ...

Table chq_sessions does not exist! ...
Initializing Cachet database ...
[2024-07-30 00:05:54] production.ERROR: Symfony\Component\Console\Exception\CommandNotFoundException: Command "cachet:install" is not defined.

Did you mean one of these?
    app:install
    migrate:install
    cachet:metrics
    cachet:seed
    cache:clear
    cache:table in /var/www/html/vendor/symfony/console/Application.php:515
Stack trace:
#0 /var/www/html/vendor/symfony/console/Application.php(183): Symfony\Component\Console\Application->find('cachet:install')
#1 /var/www/html/vendor/symfony/console/Application.php(117): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#2 /var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(107): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#3 /var/www/html/artisan(35): Illuminate\Foundation\Console\Kernel->handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#4 {main} {"identification":{"id":"a7522976-7edf-44ae-96dd-7d9257a4cbf3"}}



  [Symfony\Component\Console\Exception\CommandNotFoundException]
  Command "cachet:install" is not defined.
  Did you mean one of these?
      app:install
      migrate:install
      cachet:metrics
      cachet:seed
      cache:clear
      cache:table

Seems that they renaped app:install to cachet:install in 2.4 (yet I picked 2.3.x) - see thread.

I switched to the tag latest and it worked

builder@LuiGi:~/Workspaces/cachet$ kubectl get pods -n cachet
NAME                        READY   STATUS    RESTARTS   AGE
postgres-79d66cd6dc-87l9n   1/1     Running   0          8m20s
cachet-58ccc444dc-vkzww     1/1     Running   0          42s

I’ll try port-forwarding over to the service that fronts the pod

builder@LuiGi:~/Workspaces/cachet$ kubectl port-forward svc/cachet -n cachet 8888:80
Forwarding from 127.0.0.1:8888 -> 8000
Forwarding from [::1]:8888 -> 8000

That didn’t work

/content/images/2024/08/docmost-27.png

Using Docker Compose didn’t help either

/content/images/2024/08/cachet-02.png

Nothing was working until I removed the APP_KEY variable and launched fresh - then it spit out the desired value

builder@LuiGi:~/Workspaces/cachethq-Docker$ docker compose up
[+] Running 2/2
 ✔ Container cachethq-docker-postgres-1  Created                                                       0.0s
 ✔ Container cachethq-docker-cachet-1    Recreated                                                     0.3s
Attaching to cachet-1, postgres-1
postgres-1  |
postgres-1  | PostgreSQL Database directory appears to contain a database; Skipping initialization
postgres-1  |
postgres-1  | 2024-07-30 00:31:27.278 UTC [1] LOG:  starting PostgreSQL 12.19 on x86_64-pc-linux-musl, compiled by gcc (Alpine 13.2.1_git20240309) 13.2.1 20240309, 64-bit
postgres-1  | 2024-07-30 00:31:27.278 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
postgres-1  | 2024-07-30 00:31:27.278 UTC [1] LOG:  listening on IPv6 address "::", port 5432
postgres-1  | 2024-07-30 00:31:27.295 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
postgres-1  | 2024-07-30 00:31:27.329 UTC [27] LOG:  database system was shut down at 2024-07-30 00:31:09 UTC
postgres-1  | 2024-07-30 00:31:27.342 UTC [1] LOG:  database system is ready to accept connections
cachet-1    | Initializing Cachet container ...
cachet-1    | ERROR: Please set the 'APP_KEY=base64:O9c899Bq5oDxI12fUSl7Dk/+XI0h4e2cvznfQNG+T1o=' environment variable at runtime or in docker-compose.yml and re-launch

I replaced and launched and this time it seemed to work

builder@LuiGi:~/Workspaces/cachethq-Docker$ docker compose up
[+] Running 2/2
 ✔ Container cachethq-docker-postgres-1  Created                                                       0.0s
 ✔ Container cachethq-docker-cachet-1    Recreated                                                     0.2s
Attaching to cachet-1, postgres-1
postgres-1  |
postgres-1  | PostgreSQL Database directory appears to contain a database; Skipping initialization
postgres-1  |
postgres-1  | 2024-07-30 00:31:50.580 UTC [1] LOG:  starting PostgreSQL 12.19 on x86_64-pc-linux-musl, compiled by gcc (Alpine 13.2.1_git20240309) 13.2.1 20240309, 64-bit
postgres-1  | 2024-07-30 00:31:50.580 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
postgres-1  | 2024-07-30 00:31:50.580 UTC [1] LOG:  listening on IPv6 address "::", port 5432
postgres-1  | 2024-07-30 00:31:50.593 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
postgres-1  | 2024-07-30 00:31:50.621 UTC [27] LOG:  database system was shut down at 2024-07-30 00:31:37 UTC
postgres-1  | 2024-07-30 00:31:50.633 UTC [1] LOG:  database system is ready to accept connections
cachet-1    | Initializing Cachet container ...
cachet-1    | Attempting to connect to database ...
cachet-1    |
cachet-1    | Table chq_sessions exists! ...
cachet-1    | Nothing to migrate.
cachet-1    | Database seeding completed successfully.
cachet-1    | Starting Cachet! ...
cachet-1    | Configuration cache cleared!
cachet-1    | Configuration cached successfully!
cachet-1    | 2024-07-30 00:31:52,132 WARN For [program:queue-worker], AUTO logging used for stderr_logfile without rollover, set maxbytes > 0 to avoid filling up filesystem unintentionally
cachet-1    | 2024-07-30 00:31:52,134 INFO supervisord started with pid 73
cachet-1    | 2024-07-30 00:31:53,138 INFO spawned: 'nginx' with pid 75
cachet-1    | 2024-07-30 00:31:53,140 INFO spawned: 'php-fpm' with pid 76
cachet-1    | 2024-07-30 00:31:53,143 INFO spawned: 'queue-worker' with pid 77
cachet-1    | [30-Jul-2024 00:31:53] NOTICE: fpm is running, pid 76
cachet-1    | [30-Jul-2024 00:31:53] NOTICE: ready to handle connections
cachet-1    | 2024-07-30 00:31:54,180 INFO success: nginx entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
cachet-1    | 2024-07-30 00:31:54,181 INFO success: php-fpm entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
cachet-1    | 2024-07-30 00:31:54,181 INFO success: queue-worker entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
cachet-1    | 172.19.0.1 - - [30/Jul/2024:00:32:00 +0000] "GET / HTTP/1.1" 302 346 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"
cachet-1    | 172.19.0.1 - - [30/Jul/2024:00:32:00 +0000] "GET /setup HTTP/1.1" 200 8638 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"
cachet-1    | 172.19.0.1 - - [30/Jul/2024:00:32:01 +0000] "GET /dist/css/dashboard/dashboard.css?id=7e9267fcdd1150802d64 HTTP/1.1" 200 101290 "http://localhost/setup" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"
cachet-1    | 172.19.0.1 - - [30/Jul/2024:00:32:01 +0000] "GET /dist/js/manifest.js?id=3c768977c2574a34506e HTTP/1.1" 200 1493 "http://localhost/setup" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"
cachet-1    | 172.19.0.1 - - [30/Jul/2024:00:32:01 +0000] "GET /dist/js/vendor.js?id=669b7556d754809958ea HTTP/1.1" 200 551569 "http://localhost/setup" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"
cachet-1    | 172.19.0.1 - - [30/Jul/2024:00:32:01 +0000] "GET /img/cachet-logo.svg HTTP/1.1" 200 2917 "http://localhost/setup" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"
cachet-1    | 172.19.0.1 - - [30/Jul/2024:00:32:01 +0000] "GET /dist/js/all.js?id=fe2ebcf0bbbd7868bf49 HTTP/1.1" 200 1170252 "http://localhost/setup" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"
cachet-1    | 172.19.0.1 - - [30/Jul/2024:00:32:01 +0000] "GET /img/favicon.png HTTP/1.1" 200 6221 "http://localhost/setup" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"
cachet-1    | 172.19.0.1 - - [30/Jul/2024:00:32:01 +0000] "GET /img/favicon.ico HTTP/1.1" 200 952 "http://localhost/setup" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"

/content/images/2024/08/cachet-03.png

I’ll setup some SMTP values

/content/images/2024/08/cachet-04.png

Set my name and timezone

/content/images/2024/08/cachet-05.png

Next, I need to setup the Administrator account

/content/images/2024/08/cachet-06.png

I can now login

/content/images/2024/08/cachet-07.png

I now have an Incidents Dashboard

/content/images/2024/08/cachet-08.png

Let’s start by reporting an incident

/content/images/2024/08/cachet-09.png

I now have an Incident showing up

/content/images/2024/08/cachet-10.png

I could then add an update such as rebooting host

/content/images/2024/08/cachet-11.png

As an anonymous user, I can go to the dashboard and just view status and see we have an ongoing issue

/content/images/2024/08/cachet-12.png

Let me wrap up the incident by indicating the reboot fixed the issue

/content/images/2024/08/cachet-13.png

Which for our anonymous user base shows things are super duper again

/content/images/2024/08/cachet-14.png

Back to Kubernetes

While this seems a bit of a bizarre way to launch an application, lets try it - Ill remove the APP_KEY from the manifest and relaunch

builder@LuiGi:~/Workspaces/cachet$ kubectl delete -f manifest.yaml -n cachet
deployment.apps "postgres" deleted
deployment.apps "cachet" deleted
service "cachet" deleted
service "postgres" deleted
persistentvolumeclaim "postgres-data" deleted
builder@LuiGi:~/Workspaces/cachet$ kubectl apply -f manifest.yaml -n cachet
deployment.apps/postgres created
deployment.apps/cachet created
service/cachet created
service/postgres created
persistentvolumeclaim/postgres-data created
builder@LuiGi:~/Workspaces/cachet$ kubectl get pods -n cachet
NAME                        READY   STATUS             RESTARTS     AGE
cachet-58ccc444dc-vkzww     1/1     Terminating        0            40m
postgres-79d66cd6dc-cn5r2   0/1     Pending            0            5s
cachet-7d8555f5d9-n26pk     0/1     CrashLoopBackOff   1 (1s ago)   5s
builder@LuiGi:~/Workspaces/cachet$ kubectl logs cachet-7d8555f5d9-n26pk -n cachet
Initializing Cachet container ...
ERROR: Please set the 'APP_KEY=base64:sV+rWqsg8MOpr6fyD88Z2B7MJSpg23QfkdRkMjJVWwY=' environment variable at runtime or in docker-compose.yml and re-launch

Now I’ll try adding it back just as it asks

$ cat manifest.yaml
builder@LuiGi:~/Workspaces/cachet$ cat manifest.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgres
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
      - name: postgres
        image: postgres:12-alpine
        env:
        - name: POSTGRES_USER
          value: postgres
        - name: POSTGRES_PASSWORD
          value: postgres
        volumeMounts:
        - mountPath: /var/lib/postgresql/data
          name: postgres-data
      volumes:
      - name: postgres-data
        persistentVolumeClaim:
          claimName: postgres-data
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: cachet
spec:
  replicas: 1
  selector:
    matchLabels:
      app: cachet
  template:
    metadata:
      labels:
        app: cachet
    spec:
      containers:
      - name: cachet
        image: cachethq/docker:latest
        env:
        - name: DB_DRIVER
          value: pgsql
        - name: DB_HOST
          value: postgres
        - name: DB_PORT
          value: "5432"
        - name: DB_DATABASE
          value: postgres
        - name: DB_USERNAME
          value: postgres
        - name: DB_PASSWORD
          value: postgres
        - name: DB_PREFIX
          value: chq_
        - name: APP_KEY
          value: base64:sV+rWqsg8MOpr6fyD88Z2B7MJSpg23QfkdRkMjJVWwY=
        - name: APP_LOG
          value: errorlog
        - name: APP_ENV
          value: production
        - name: APP_DEBUG
          value: "false"
        - name: DEBUG
          value: "false"
        ports:
        - containerPort: 8000
---
apiVersion: v1
kind: Service
metadata:
  name: cachet
spec:
  selector:
    app: cachet
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8000
---
apiVersion: v1
kind: Service
metadata:
  name: postgres
spec:
  selector:
    app: postgres
  ports:
    - protocol: TCP
      port: 5432
      targetPort: 5432
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-data
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi
  storageClassName: local-path

And reapply

builder@LuiGi:~/Workspaces/cachet$ kubectl apply -f manifest.yaml -n cachet
deployment.apps/postgres unchanged
deployment.apps/cachet configured
service/cachet unchanged
service/postgres unchanged
persistentvolumeclaim/postgres-data unchanged

That seems better

builder@LuiGi:~/Workspaces/cachet$ kubectl logs cachet-54995dbd64-jzxxl -n cachet | tail -n 15
 Do you really wish to run this command? (yes/no) [no]:
 > Command Cancelled!
Starting Cachet! ...
Configuration cache cleared!
Configuration cached successfully!
2024-07-30 00:50:53,666 WARN For [program:queue-worker], AUTO logging used for stderr_logfile without rollover, set maxbytes > 0 to avoid filling up filesystem unintentionally
2024-07-30 00:50:53,668 INFO supervisord started with pid 83
2024-07-30 00:50:54,671 INFO spawned: 'nginx' with pid 85
2024-07-30 00:50:54,673 INFO spawned: 'php-fpm' with pid 86
2024-07-30 00:50:54,676 INFO spawned: 'queue-worker' with pid 87
[30-Jul-2024 00:50:54] NOTICE: fpm is running, pid 86
[30-Jul-2024 00:50:54] NOTICE: ready to handle connections
2024-07-30 00:50:55,725 INFO success: nginx entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2024-07-30 00:50:55,725 INFO success: php-fpm entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2024-07-30 00:50:55,725 INFO success: queue-worker entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)

This time it works!

builder@LuiGi:~/Workspaces/cachet$ kubectl port-forward svc/cachet -n cachet 8888:80
Forwarding from 127.0.0.1:8888 -> 8000
Forwarding from [::1]:8888 -> 8000
Handling connection for 8888
Handling connection for 8888
Handling connection for 8888
Handling connection for 8888
Handling connection for 8888

/content/images/2024/08/cachet-15.png

Looking good!

/content/images/2024/08/cachet-16.png

I’ll try subscribing to updates

/content/images/2024/08/cachet-17.png

However, that threw an error

/content/images/2024/08/cachet-18.png

Nothing really shows up in the logs so it must store errors in the database somewhere

builder@LuiGi:~/Workspaces/cachet$ kubectl logs cachet-54995dbd64-jzxxl -n cachet | tail -n 15
127.0.0.1 - - [30/Jul/2024:00:54:35 +0000] "GET /fonts/ionicons.ttf?v=2.0.1 HTTP/1.1" 200 188508 "http://localhost:8888/dist/css/dashboard/dashboard.css?id=b6a9327dd3b9b7c7ed2d" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"
127.0.0.1 - - [30/Jul/2024:00:54:35 +0000] "POST /setup/step1 HTTP/1.1" 200 43 "http://localhost:8888/setup" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"
127.0.0.1 - - [30/Jul/2024:00:55:11 +0000] "POST /setup/step2 HTTP/1.1" 200 43 "http://localhost:8888/setup" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"
127.0.0.1 - - [30/Jul/2024:00:55:31 +0000] "POST /setup/step3 HTTP/1.1" 200 43 "http://localhost:8888/setup" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"
127.0.0.1 - - [30/Jul/2024:00:55:37 +0000] "GET /dashboard HTTP/1.1" 302 386 "http://localhost:8888/setup" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"
127.0.0.1 - - [30/Jul/2024:00:55:37 +0000] "GET /auth/login HTTP/1.1" 200 1172 "http://localhost:8888/setup" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"
127.0.0.1 - - [30/Jul/2024:00:55:37 +0000] "GET /img/cachet-logo@2x.png HTTP/1.1" 200 4736 "http://localhost:8888/auth/login" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"
127.0.0.1 - - [30/Jul/2024:00:55:45 +0000] "POST /auth/login HTTP/1.1" 302 382 "http://localhost:8888/auth/login" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"
127.0.0.1 - - [30/Jul/2024:00:55:45 +0000] "GET /dashboard HTTP/1.1" 200 2650 "http://localhost:8888/auth/login" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"
127.0.0.1 - - [30/Jul/2024:00:55:46 +0000] "GET /api/v1/version HTTP/1.1" 200 114 "http://localhost:8888/dashboard" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"
127.0.0.1 - - [30/Jul/2024:00:57:06 +0000] "GET / HTTP/1.1" 200 2036 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"
127.0.0.1 - - [30/Jul/2024:00:57:06 +0000] "GET /dist/css/app.css?id=c7bf7628a7a22dfec2ed HTTP/1.1" 200 16225 "http://localhost:8888/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"
127.0.0.1 - - [30/Jul/2024:00:57:15 +0000] "GET /subscribe HTTP/1.1" 200 1942 "http://localhost:8888/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"
127.0.0.1 - - [30/Jul/2024:00:57:56 +0000] "POST /subscribe HTTP/1.1" 500 3175 "http://localhost:8888/subscribe" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"
127.0.0.1 - - [30/Jul/2024:00:58:25 +0000] "GET / HTTP/1.1" 200 2036 "http://localhost:8888/subscribe" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36" "-"

Exposing

Let’s create an A Record on the freshbrewed.science domain

$ cat r53-cachet.json
{
  "Comment": "CREATE status fb.s A record ",
  "Changes": [
    {
      "Action": "CREATE",
      "ResourceRecordSet": {
        "Name": "status.freshbrewed.science",
        "Type": "A",
        "TTL": 300,
        "ResourceRecords": [
          {
            "Value": "75.73.224.240"
          }
        ]
      }
    }
  ]
}
$ aws route53 change-resource-record-sets --hosted-zone-id Z39E8QFU0F9PZP --change-batch file://r53-cachet.json
{
    "ChangeInfo": {
        "Id": "/change/C07038411HVXKOMVU2KU9",
        "Status": "PENDING",
        "SubmittedAt": "2024-07-30T01:03:01.729000+00:00",
        "Comment": "CREATE status fb.s A record "
    }
}

Now I can create an ingress

builder@LuiGi:~/Workspaces/cachet$ cat ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    ingress.kubernetes.io/ssl-redirect: "true"
    kubernetes.io/ingress.class: nginx
    kubernetes.io/tls-acme: "true"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
  name: status
spec:
  rules:
  - host: status.freshbrewed.science
    http:
      paths:
      - backend:
          service:
            name: cachet
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific
  tls:
  - hosts:
    - status.freshbrewed.science
    secretName: status-tls
builder@LuiGi:~/Workspaces/cachet$ kubectl apply -f ./ingress.yaml -n cachet
ingress.networking.k8s.io/status created

I see the cert created so I can test the site

$ kubectl get cert -n cachet
NAME         READY   SECRET       AGE
status-tls   True    status-tls   40m

I can now load a status page at http://status.freshbrewed.science

/content/images/2024/08/cachet-19.png

But as expected, Subscribe fails

/content/images/2024/08/cachet-20.png

Since it fails, let’s just disable it in the settings as well as add more days and an “About” section

/content/images/2024/08/cachet-21.png

That looks good

/content/images/2024/08/cachet-22.png

API Usage

We can see in our user settings an API token we can use

/content/images/2024/08/cachet-23.png

The example in the docs shows

curl -H "Content-Type: application/json;" -H "X-Cachet-Token: YOUR_KEY_HERE" -d '{"name":"API","description":"An example description","status":1}' http://status.cachethq.io/api/v1/components

Let’s use our token to get active incidents, which are empty

$ curl -H "Content-Type: application/json;" -H "X-Cachet-Token: YfmGr6tidrpw5nRKBo2m" https://status.freshbrewed.science/api/v1/incidents
{"meta":{"pagination":{"total":0,"count":0,"per_page":20,"current_page":1,"total_pages":1,"links":{"next_page":null,"previous_page":null}}},"data":[]}

Since I don’t see specifics on posting to incidents, I’ll try a blank post to see what feedback I get from the REST API

$ curl -X POST -H "Content-Type: application/json;" -H "X-Cachet-Token: YfmGr6tidrpw5nRKBo2m" https://status.freshbrewed.science/api/v1/incidents
{"errors":[{"id":"543d57a8-d028-4b30-9b09-2becf5c717c2","status":400,"title":"Bad Request","detail":"The request cannot be fulfilled due to bad syntax.","meta":{"details":["The name field is required.","The status field is required."]}}]}

I can post a basic status providing I pass message, name and status:

$ curl -X POST -H "Content-Type: application/json;" -H "X-Cachet-Token: YfmGr6tidrpw5nRKBo2m" https://status.freshbrewed.science/api/v1/incidents -d '{"name": "This Is A Test", "message": "This Is A Test", "description":"An example description","status":1}'
{"data":{"stickied":false,"notifications":false,"user_id":1,"name":"This Is A Test","status":1,"visible":1,"message":"This Is A Test","occurred_at":"2024-07-30 06:01:15","updated_at":"2024-07-30 06:01:15","created_at":"2024-07-30 06:01:15","id":1,"is_resolved":false,"component":null,"updates":[],"human_status":"Investigating","latest_update_id":null,"latest_status":1,"latest_human_status":"Investigating","latest_icon":"icon ion-flag oranges","permalink":"https:\/\/status.freshbrewed.science\/incidents\/1","duration":0,"meta":[]}}

Which now shows up

/content/images/2024/08/cachet-24.png

I can see that Status 1 matches “Investigating”. I’ll work through the status fields and visibility next.

status description
1 Investigating
2 Identified
3 Watching
4 Fixed

If you set "visible":0 then it marks it as “Only visible to logged in uses” (Incident Visibility). The default is 1 which is visible to public.

If you set "stickied":true then it marks it as “Stickied” (Stick Incident). The default is false which is not stickied.

I did find that when I rotate my API token, it still responds, but just as an anonymous user

$ curl -H "Content-Type: applicat" http -H "X-Cachet-Token: xxxxxx" https://status.freshbrewed.science/api/v1/incidents
{"meta":{"pagination":{"total":0,"count":0,"per_page":20,"current_page":1,"total_pages":1,"links":{"next_page":null,"previous_page":null}}},"data":[]}

Datadog Integration

Let’s say we wanted Datadog to post to our status directly

We can go to Integrations and pull up “Webhooks”

/content/images/2024/08/cachet-25.png

I can see my existing Webhook Endpoints

/content/images/2024/08/cachet-26.png

I’ll build out a payload

{
    "name": "$EVENT_TITLE",
    "message": "$EVENT_MSG",
    "description": "Datadog $ORG_NAME reports Incident $ID of type $EVENT_TYPE. Last updated $LAST_UPDATED",
    "status": 1
}

/content/images/2024/08/cachet-27.png

Note: on save, I had to change the Headers to {"X-Cachet-Token": "xxxxxxxxxxxxxxxxxxx"}

/content/images/2024/08/cachet-28.png

To test, I’ll add as a notification endpoint on an existing monitor

/content/images/2024/08/cachet-29.png

I can then click “Run Test” at the bottom, then choose my Alert Type and click “Run Test”

/content/images/2024/08/cachet-30.png

I can now see the Datadog posted event

/content/images/2024/08/cachet-31.png

I’m going to swap description and message in my payload

{
    "name": "$EVENT_TITLE",
    "description": "$EVENT_MSG",
    "message": "Datadog $ORG_NAME reports Incident $ID of type $EVENT_TYPE. Last updated $LAST_UPDATED",
    "status": 1
}

And try it again

/content/images/2024/08/cachet-32.png

I decided to check into the specifics on Datadog webhooks documentation to build a better alert

I switched to:

{
    "name": "Datadog: $ALERT_TITLE ($ALERT_TYPE)",
    "description": "$EVENT_MSG",
    "message": "Datadog $ORG_NAME reports $ALERT_STATUS ($ALERT_QUERY).  Priority $ALERT_PRIORITY. Last updated $LAST_UPDATED. Tags; $TAGS",
    "status": 1
}

I think I like this best:

/content/images/2024/08/cachet-33.png

I now have it saved

/content/images/2024/08/cachet-34.png

Now we come to a bit of a conundrum. I have an alert that monitors production Kubernetes clusters

/content/images/2024/08/cachet-35.png

The irony is it uses a webservice on that very cluster to turn on a desk lamp that shows errors - kind of hard to reach if the cluster in question is down. Moreover, if the production cluster is in a bad way, I would expect the Cachet instance on it to also be in a bad way.

For now, I won’t add to this, but I need to likely move Cachet to a cloud service if it is to include monitoring the production cluster.

I could do a unique port through my firewall but then I give up on HTTPS (or have to deal with it manually). Either way, I do think there is a bit of need to either host it on my NAS itself (which is phenomenally durable) or move it to a cloud service.

Summary

Today we looked at Docmost which is an excellent internal Documentation Open-Source offering. I moved it from Docker to Kubernetes building out a helm chart you are welcome to fork and use.

I actually thought Cachet might be a dead project. It’s over 9 years old with the last release nearly a year ago in November. It’s PHP, but that also makes it very light and fast. There is a bit of a strange flow (to me) in how the API key is generated. Regardless, we figured out how to make that into a proper Kubernetes manifest and host it in Kubernetes with Redis/Valkey and PostgreSQL. I then added a TLS ingress before exploring the REST API and integrating it with Datadog.

I do think for a proper HA instance I need to move it to the cloud, but we’ll save that for another day.

Open-Source Incident Documentation docmost cachet

Have something to add? Feedback? You can use the feedback form

Isaac Johnson

Isaac Johnson

Cloud Solutions Architect

Isaac is a CSA and DevOps engineer who focuses on cloud migrations and devops processes. He also is a dad to three wonderful daughters (hence the references to Princess King sprinkled throughout the blog).

Theme built by C.S. Rhymes