Published: Jun 20, 2024 by Isaac Johnson
Today, we’ll look at a few apps that have been in my backlog to check out. The first is from Linuxserver and is Netbox. It’s a Datacenter management suite aimed to create a full site management platform. The next is a local binary, ‘Encrypted Notedpad II’ which is a go-based PGP encrypted Notepad. One has to compile to use as the binaries are pay-for. Lastly, we’ll look at CryptPad, a nice Open-Source web-based app that is like Google Docs with extra encryption and destruction features.
Netbox
From the Linuxserver group comes Netbox.
We can launch with docker using
docker run -d \
--name=netbox \
-e PUID=1000 \
-e PGID=1000 \
-e TZ=Etc/UTC \
-e SUPERUSER_EMAIL= \
-e SUPERUSER_PASSWORD= \
-e ALLOWED_HOST= \
-e DB_NAME= \
-e DB_USER= \
-e DB_PASSWORD= \
-e DB_HOST= \
-e DB_PORT= \
-e REDIS_HOST= \
-e REDIS_PORT= \
-e REDIS_PASSWORD= \
-e REDIS_DB_TASK= \
-e REDIS_DB_CACHE= \
-e BASE_PATH= `#optional` \
-e REMOTE_AUTH_ENABLED= `#optional` \
-e REMOTE_AUTH_BACKEND= `#optional` \
-e REMOTE_AUTH_HEADER= `#optional` \
-e REMOTE_AUTH_AUTO_CREATE_USER= `#optional` \
-e REMOTE_AUTH_DEFAULT_GROUPS= `#optional` \
-e REMOTE_AUTH_DEFAULT_PERMISSIONS= `#optional` \
-p 8000:8000 \
-v /path/to/netbox/config:/config \
--restart unless-stopped \
lscr.io/linuxserver/netbox:latest
But I want to skip right to Kubernetes.
I’ll first create the postgres and redis instances
$ cat database.yaml
apiVersion: v1
kind: Service
metadata:
name: postgres-service
spec:
selector:
app: postgres
ports:
- protocol: TCP
port: 5432
targetPort: 5432
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres-deployment
spec:
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:latest
env:
- name: POSTGRES_USER
value: mydbuser
- name: POSTGRES_PASSWORD
value: NotThePassWord
ports:
- containerPort: 5432
volumeMounts:
- name: postgres-pvc
mountPath: /var/lib/postgresql/data
volumes:
- name: postgres-pvc
persistentVolumeClaim:
claimName: postgres-pvc
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-deployment
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:latest
env:
- name: REDIS_PASSWORD
value: myredispassword
ports:
- containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
name: redis-service
spec:
selector:
app: redis
ports:
- protocol: TCP
port: 6379
targetPort: 6379
I’ll create the namespace
$ kubectl create ns netbox
namespace/netbox created
Then I can add the objects
$ kubectl apply -f database.yaml -n netbox
service/postgres-service created
deployment.apps/postgres-deployment created
persistentvolumeclaim/postgres-pvc created
deployment.apps/redis-deployment created
service/redis-service created
A quick shows everything is in order
$ kubectl get pvc -n netbox
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
postgres-pvc Bound pvc-438b6117-83e8-4030-9bfb-5bb2b2385f90 1Gi RWO local-path 4m17s
$ kubectl get pods -n netbox
NAME READY STATUS RESTARTS AGE
redis-deployment-5f78879c54-9qb22 1/1 Running 0 4m21s
postgres-deployment-8598888695-fbdc7 1/1 Running 0 109s
$ kubectl get svc -n netbox
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
postgres-service ClusterIP 10.43.92.40 <none> 5432/TCP 4m32s
redis-service ClusterIP 10.43.78.70 <none> 6379/TCP 4m31s
Next, If I did this right, I should have the right Redis and PostgreSQL in the app yaml
$ cat app.yaml
apiVersion: v1
kind: Service
metadata:
name: netbox-service
spec:
selector:
app: netbox
ports:
- protocol: TCP
port: 8000
targetPort: 8000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: netbox-deployment
spec:
replicas: 1
selector:
matchLabels:
app: netbox
template:
metadata:
labels:
app: netbox
spec:
containers:
- name: netbox
image: lscr.io/linuxserver/netbox:latest
env:
- name: PUID
value: "1000"
- name: PGID
value: "1000"
- name: TZ
value: "Etc/UTC"
- name: SUPERUSER_EMAIL
value: "isaac@freshbrewed.science"
- name: SUPERUSER_PASSWORD
value: "FakePasswordNotIt"
- name: DB_HOST
value: "postgres-service"
- name: DB_USER
value: "mydbuser"
- name: DB_PASSWORD
value: "NotThePassWord"
- name: REDIS_HOST
value: "redis-service"
- name: REDIS_PASSWORD
value: "myredispassword"
# Add other environment variables as needed
ports:
- containerPort: 8000
volumeMounts:
- name: netbox-config
mountPath: /config
volumes:
- name: netbox-config
persistentVolumeClaim:
claimName: netbox-pvc
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: netbox-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
I can then apply
$ kubectl apply -f ./app.yaml -n netbox
service/netbox-service created
deployment.apps/netbox-deployment created
persistentvolumeclaim/netbox-pvc created
I can see the new pod come up
$ kubectl get pods -n netbox
NAME READY STATUS RESTARTS AGE
redis-deployment-5f78879c54-9qb22 1/1 Running 0 12m
postgres-deployment-8598888695-fbdc7 1/1 Running 0 9m50s
netbox-deployment-54dd46d65-xbt7m 1/1 Running 0 2m36s
I think I can now add an A record
$ 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
Then an ingress that could use it
$ cate netbox.ingress.yaml
$ cat netbox.ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
cert-manager.io/cluster-issuer: azuredns-tpkpw
ingress.kubernetes.io/ssl-redirect: "true"
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.org/websocket-services: netbox-service
name: netbox-ingress
spec:
rules:
- host: netbox.tpk.pw
http:
paths:
- backend:
service:
name: netbox-service
port:
number: 8000
path: /
pathType: Prefix
tls:
- hosts:
- netbox.tpk.pw
secretName: netbox-tls
which can be easily applied
$ kubectl apply -f ./netbox.ingress.yaml -n netbox
ingress.networking.k8s.io/netbox-ingress created
I tend to gloss over it, but I should from time to time point out that the cluserissuer uses Azure DNS with an SP.
It’s setup like
$ kubectl get clusterissuer azuredns-tpkpw -o yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
creationTimestamp: "2024-03-03T17:31:15Z"
generation: 1
name: azuredns-tpkpw
resourceVersion: "154819"
uid: d3eb617b-7784-454a-9be5-60529d50eeab
spec:
acme:
email: isaac.johnson@gmail.com
preferredChain: ""
privateKeySecretRef:
name: azuredns-tpkpw
server: https://acme-v02.api.letsencrypt.org/directory
solvers:
- dns01:
azureDNS:
clientID: 7d420c37-xxxx-xxxx-xxxx-cd3e3066ec00
clientSecretSecretRef:
key: client-secret
name: azuredns-config
environment: AzurePublicCloud
hostedZoneName: tpk.pw
resourceGroupName: idjdnsrg
subscriptionID: d955c0ba-xxxx-xxxx-xxxx-a29a-8fed74cbb22d
tenantID: 28c575f6-xxxx-xxxx-xxxx-8e7c-7e6d1ba0eb4a
status:
acme:
lastPrivateKeyHash: EB1ZBoDVqpcHfESDWkjtRqFizP+iUjLUnnarg1/tKqk=
lastRegisteredEmail: isaac.johnson@gmail.com
uri: https://acme-v02.api.letsencrypt.org/acme/acct/1581682847
conditions:
- lastTransitionTime: "2024-03-03T17:31:16Z"
message: The ACME account was registered with the ACME server
observedGeneration: 1
reason: ACMEAccountRegistered
status: "True"
type: Ready
Once I see the cert is valid
$ kubectl get cert -n netbox
NAME READY SECRET AGE
netbox-tls True netbox-tls 2m32s
Redis auth seemed to block me, so I tore the whole stack down and recreated. I also added health checks and startup probes to the app:
$ cat app.yaml
apiVersion: v1
kind: Service
metadata:
name: netbox-service
spec:
selector:
app: netbox
ports:
- protocol: TCP
port: 8000
targetPort: 8000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: netbox-deployment
spec:
replicas: 1
selector:
matchLabels:
app: netbox
template:
metadata:
labels:
app: netbox
spec:
containers:
- name: netbox
image: lscr.io/linuxserver/netbox:latest
env:
- name: PUID
value: "1000"
- name: PGID
value: "1000"
- name: TZ
value: "Etc/UTC"
- name: SUPERUSER_EMAIL
value: "isaac@freshbrewed.science"
- name: SUPERUSER_PASSWORD
value: "FakePasswordNotIt"
- name: DB_HOST
value: "postgres-service"
- name: DB_USER
value: "mydbuser"
- name: DB_PASSWORD
value: "NotThePassWord"
- name: REDIS_HOST
value: "redis-service"
# Add other environment variables as needed
ports:
- containerPort: 8000
volumeMounts:
- name: netbox-config
mountPath: /config
readinessProbe:
tcpSocket:
port: 8000
initialDelaySeconds: 30
periodSeconds: 10
failureThreshold: 3
livenessProbe:
tcpSocket:
port: 8000
initialDelaySeconds: 60
periodSeconds: 30
failureThreshold: 5
volumes:
- name: netbox-config
persistentVolumeClaim:
claimName: netbox-pvc
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: netbox-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
and the services
$ cat database.yaml
apiVersion: v1
kind: Service
metadata:
name: postgres-service
spec:
selector:
app: postgres
ports:
- protocol: TCP
port: 5432
targetPort: 5432
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres-deployment
spec:
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:latest
env:
- name: POSTGRES_USER
value: mydbuser
- name: POSTGRES_PASSWORD
value: NotThePassWord
- name: POSTGRES_DB
value: netbox
ports:
- containerPort: 5432
volumeMounts:
- name: postgres-pvc
mountPath: /var/lib/postgresql/data
volumes:
- name: postgres-pvc
persistentVolumeClaim:
claimName: postgres-pvc
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-deployment
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:latest
ports:
- containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
name: redis-service
spec:
selector:
app: redis
ports:
- protocol: TCP
port: 6379
targetPort: 6379
But I keep getting a 400 bad request
i did some searching and others suggested the absence of an “ALLOWED_HOSTS” would do that.
I added to the app yaml
... snip ...
- name: ALLOWED_HOST
value: "netbox.tpk.pw"
... snip ...
Then applied
$ kubectl apply -f ./netbox.app.yaml -n netbox
service/netbox-service unchanged
deployment.apps/netbox-deployment configured
persistentvolumeclaim/netbox-pvc unchanged
Gemini suggested
... snip ...
- name: ALLOWED_HOST
value: "*"
... snip ...
I can see it’s running just fine
$ kubectl logs netbox-deployment-84956dc6d-ldk25 -n netbox
[migrations] started
[migrations] no migrations found
───────────────────────────────────────
██╗ ███████╗██╗ ██████╗
██║ ██╔════╝██║██╔═══██╗
██║ ███████╗██║██║ ██║
██║ ╚════██║██║██║ ██║
███████╗███████║██║╚██████╔╝
╚══════╝╚══════╝╚═╝ ╚═════╝
Brought to you by linuxserver.io
───────────────────────────────────────
To support LSIO projects visit:
https://www.linuxserver.io/donate/
───────────────────────────────────────
GID/UID
───────────────────────────────────────
User UID: 1000
User GID: 1000
───────────────────────────────────────
Linuxserver.io version: v4.0.3-ls204
Build-date: 2024-06-04T18:42:09+00:00
───────────────────────────────────────
Building local documentation
/lsiopy/lib/python3.12/site-packages/strawberry/utils/deprecations.py:23: UserWarning: _type_definition is deprecated, use __strawberry_definition__ instead
self.warn()
Operations to perform:
Apply all migrations: account, auth, circuits, contenttypes, core, dcim, django_rq, extras, ipam, sessions, social_django, taggit, tenancy, users, virtualization, vpn, wireless
Running migrations:
No migrations to apply.
Superuser creation skipped. Already exists.
[custom-init] No custom files found, skipping...
[uWSGI] getting INI configuration from uwsgi.ini
[uwsgi-static] added mapping for /static => static
*** Starting uWSGI 2.0.25.1 (64bit) on [Wed Jun 5 11:32:47 2024] ***
compiled with version: 13.2.1 20240309 on 17 May 2024 06:11:37
os: Linux-5.15.0-97-generic #107-Ubuntu SMP Wed Feb 7 13:26:48 UTC 2024
nodename: netbox-deployment-84956dc6d-ldk25
machine: x86_64
clock source: unix
pcre jit disabled
detected number of CPU cores: 4
current working directory: /app/netbox/netbox
detected binary path: /usr/sbin/uwsgi
your memory page size is 4096 bytes
detected max file descriptor number: 1048576
building mime-types dictionary from file /etc/mime.types...1390 entry found
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uwsgi socket 0 bound to TCP address :8000 fd 3
Python version: 3.12.3 (main, Apr 18 2024, 07:52:31) [GCC 13.2.1 20240309]
PEP 405 virtualenv detected: /lsiopy
Set PythonHome to /lsiopy
Connection to localhost (127.0.0.1) 8000 port [tcp/*] succeeded!
Python main interpreter initialized at 0x7fb38612e688
python threads support enabled
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 203184 bytes (198 KB) for 1 cores
*** Operational MODE: single process ***
running "exec:python3 ./manage.py collectstatic --noinput" (pre app)...
[ls.io-init] done.
493 static files copied to '/app/netbox/netbox/static'.
running "exec:python3 ./manage.py remove_stale_contenttypes --no-input" (pre app)...
running "exec:python3 ./manage.py clearsessions" (pre app)...
WSGI app 0 (mountpoint='') ready in 2 seconds on interpreter 0x7fb38612e688 pid: 156 (default app)
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI master process (pid: 156)
spawned uWSGI worker 1 (pid: 191, cores: 1)
[uwsgi-daemons] spawning "python3 ./manage.py rqworker" (uid: 1000 gid: 1000)
No queues have been specified. This process will service the following queues by default: high, default, low
11:33:20 Worker rq:worker:6107c061b3de4c22a1ae273d7e071532 started with PID 192, version 1.16.2
11:33:20 Subscribing to channel rq:pubsub:6107c061b3de4c22a1ae273d7e071532
11:33:20 *** Listening on high, default, low...
11:33:20 Scheduler for default, high, low started with PID 194
11:33:20 Cleaning registries for queue: high
11:33:20 Cleaning registries for queue: default
11:33:20 Cleaning registries for queue: low
[pid: 191|app: 0|req: 1/1] 10.42.0.20 () {54 vars in 1004 bytes} [Wed Jun 5 11:33:28 2024] GET /favicon.ico => generated 143 bytes in 6307 msecs (HTTP/1.1 400) 3 headers in 121 bytes (1 switches on core 0)
[pid: 191|app: 0|req: 2/2] 10.42.0.20 () {58 vars in 1103 bytes} [Wed Jun 5 11:33:44 2024] GET / => generated 143 bytes in 11 msecs (HTTP/1.1 400) 3 headers in 121 bytes (1 switches on core 0)
[pid: 191|app: 0|req: 3/3] 10.42.0.20 () {54 vars in 1004 bytes} [Wed Jun 5 11:33:44 2024] GET /favicon.ico => generated 143 bytes in 12 msecs (HTTP/1.1 400) 3 headers in 121 bytes (1 switches on core 0)
[pid: 191|app: 0|req: 4/4] 10.42.0.20 () {58 vars in 1103 bytes} [Wed Jun 5 11:33:45 2024] GET / => generated 143 bytes in 11 msecs (HTTP/1.1 400) 3 headers in 121 bytes (1 switches on core 0)
[pid: 191|app: 0|req: 5/5] 10.42.0.20 () {54 vars in 1004 bytes} [Wed Jun 5 11:33:45 2024] GET /favicon.ico => generated 143 bytes in 18 msecs (HTTP/1.1 400) 3 headers in 121 bytes (1 switches on core 0)
But the app just dumps
Same with just a basic port-forward
Sometimes these settings are populated into the database at create time. I’ll try a full rotation of the stack (minus ingress)
$ kubectl delete -f ./netbox.db.yaml -n netbox
service "postgres-service" deleted
deployment.apps "postgres-deployment" deleted
persistentvolumeclaim "postgres-pvc" deleted
deployment.apps "redis-deployment" deleted
service "redis-service" deleted
$ kubectl delete -f ./netbox.app.yaml -n netbox
service "netbox-service" deleted
deployment.apps "netbox-deployment" deleted
persistentvolumeclaim "netbox-pvc" deleted
$ kubectl apply -f ./netbox.db.yaml -n netbox
service/postgres-service created
deployment.apps/postgres-deployment created
persistentvolumeclaim/postgres-pvc created
deployment.apps/redis-deployment created
service/redis-service created
# wait for the pods to come up
$ kubectl apply -f ./netbox.app.yaml -n netbox
service/netbox-service created
deployment.apps/netbox-deployment created
persistentvolumeclaim/netbox-pvc created
That was it!
seems my next issue is the superuser email and password i used are not taking
with the error
I verified the login
root@netbox-deployment-84956dc6d-fwsgx:/# set | grep SUPER
SUPERUSER_EMAIL=isaac@freshbrewed.science
SUPERUSER_PASSWORD=FakePasswordNotIt
When I looked up some KT on user adds, seems the username is admin, that is just “admin’s email”.
When I used admin
and FakePasswordNotIt
it worked.
There is a lot here, I admit
However, I found myself just poking around looking for some kind of automation, scanning, something:
At the least there appear to be webhooks
That can be tied to event rules
There is also a rich REST API
Adding users
I can hop on the pod to create a new super user if either I forgot the admin password or am locked out
$ kubectl exec -it netbox-deployment-84956dc6d-fwsgx -n netbox -- /bin/bash
root@netbox-deployment-84956dc6d-fwsgx:/# cd /app/netbox/netbox
root@netbox-deployment-84956dc6d-fwsgx:/app/netbox/netbox# python3 ./manage.py createsuperuser
Username: isaac
Email address: isaac.johnson@gmail.com
Password:
Password (again):
Superuser created successfully.
which I could show works
I can also use it to change a password
root@netbox-deployment-84956dc6d-fwsgx:/app/netbox/netbox# python3 ./manage.py changepassword isaac
Changing password for user 'isaac'
Password:
Password (again):
Password changed successfully for user 'isaac'
Encrypted Notepad 2
You can find EncryptedNotepad2 on Github. It’s the logical successor to Encrypted Notepad which used to be on SourceForge.
You can just buy it from the author if you want and download compiled binaries.
However, we’ll build it ourselves.
Just clone the repo
builder@DESKTOP-QADGF36:~/Workspaces$ git clone https://github.com/ivoras/EncryptedNotepad2.git
Cloning into 'EncryptedNotepad2'...
remote: Enumerating objects: 254, done.
remote: Counting objects: 100% (254/254), done.
remote: Compressing objects: 100% (176/176), done.
remote: Total 254 (delta 143), reused 180 (delta 72), pack-reused 0
Receiving objects: 100% (254/254), 1.92 MiB | 7.73 MiB/s, done.
Resolving deltas: 100% (143/143), done.
builder@DESKTOP-QADGF36:~/Workspaces$ cd EncryptedNotepad2/
My focal just had GCC 9, so I needed to add 11
I also needed some X11 libraries
sudo apt install libxft-dev libxcursor-dev libxrandr-dev libxinerama-dev libxi-dev mesa-common-dev golang gcc libgl1-mesa-dev xorg-dev
I saw the build
$ go build
go build github.com/go-gl/gl/v2.1/gl:
# pkg-config --cflags -- gl gl
Package gl was not found in the pkg-config search path.
Perhaps you should add the directory containing `gl.pc'
to the PKG_CONFIG_PATH environment variable
No package 'gl' found
Package gl was not found in the pkg-config search path.
Perhaps you should add the directory containing `gl.pc'
to the PKG_CONFIG_PATH environment variable
No package 'gl' found
pkg-config: exit status 1
Then i saw a post on stackoverflow that suggested fixing the PKG_CONFIG_PATH
builder@DESKTOP-QADGF36:~/Workspaces/EncryptedNotepad2$ export PKG_CONFIG_PATH=/usr/lib/x86_64-linux-gnu/pkgconfig
builder@DESKTOP-QADGF36:~/Workspaces/EncryptedNotepad2$ go build
github.com/ivoras/EncryptedNotepad2: cannot compile Go 1.22 code
I then had to download the latest go from godev
I fixed my path (since ubuntu has 1.13 in there) and tried again
builder@DESKTOP-QADGF36:~/Workspaces/EncryptedNotepad2$ export PATH=/usr/local/go/bin:$PATH
builder@DESKTOP-QADGF36:~/Workspaces/EncryptedNotepad2$ go build
I can now launch it from WSL
I tried building in Windows as well
C:\Users\isaac\Workspaces\EncryptedNotepad2>go build
go: downloading fyne.io/fyne/v2 v2.4.5
go: downloading github.com/ProtonMail/gopenpgp/v2 v2.7.5
go: downloading github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95
go: downloading github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f
go: downloading github.com/pkg/errors v0.9.1
go: downloading golang.org/x/crypto v0.14.0
go: downloading golang.org/x/text v0.13.0
go: downloading github.com/cloudflare/circl v1.3.3
go: downloading github.com/fsnotify/fsnotify v1.6.0
go: downloading golang.org/x/sys v0.13.0
go: downloading github.com/go-text/typesetting v0.1.0
go: downloading github.com/yuin/goldmark v1.5.5
go: downloading golang.org/x/image v0.11.0
go: downloading github.com/fredbi/uri v1.0.0
go: downloading fyne.io/systray v1.10.1-0.20231115130155-104f5ef7839e
go: downloading github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2
go: downloading github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240306074159-ea2d69986ecb
go: downloading github.com/go-text/render v0.1.0
go: downloading github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef
go: downloading github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c
go: downloading github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6
go: downloading github.com/jsummers/gobmp v0.0.0-20151104160322-e2ba15ffa76e
go: downloading github.com/tevino/abool v1.2.0
go: downloading golang.org/x/net v0.17.0
package github.com/ivoras/EncryptedNotepad2
imports fyne.io/fyne/v2/app
imports fyne.io/fyne/v2/internal/driver/glfw
imports fyne.io/fyne/v2/internal/driver/common
imports fyne.io/fyne/v2/internal/painter/gl
imports github.com/go-gl/gl/v2.1/gl: build constraints exclude all Go files in C:\Users\isaac\go\pkg\mod\github.com\go-gl\gl@v0.0.0-20211210172815-726fda9656d6\v2.1\gl
I tried manually installing deps
C:\Users\isaac\Workspaces\EncryptedNotepad2>go get fyne.io/fyne/v2/app
go: downloading fyne.io/fyne v1.4.3
go: downloading github.com/gopherjs/gopherjs v1.17.2
go: downloading github.com/godbus/dbus/v5 v5.1.0
go: downloading honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2
go: downloading github.com/stretchr/testify v1.8.4
go: downloading github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe
go: downloading github.com/fyne-io/glfw-js v0.0.0-20220120001248-ee7290d23504
go: downloading golang.org/x/mobile v0.0.0-20230531173138-3c911d8e3eda
go: downloading github.com/pmezard/go-difflib v1.0.0
go: downloading github.com/davecgh/go-spew v1.1.1
go: downloading gopkg.in/yaml.v3 v3.0.1
C:\Users\isaac\Workspaces\EncryptedNotepad2>go get fyne.io/fyne/v2/internal/driver/glfw
C:\Users\isaac\Workspaces\EncryptedNotepad2>go get fyne.io/fyne/v2/internal/driver/common
C:\Users\isaac\Workspaces\EncryptedNotepad2>go get fyne.io/fyne/v2/internal/painter/gl
C:\Users\isaac\Workspaces\EncryptedNotepad2>go get github.com/go-gl/gl/v2.1/gl
go: downloading github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71
go: upgraded github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6 => v0.0.0-20231021071112-07e5d0ea2e71
But no matter what i did, i just got stuck with
C:\Users\isaac\Workspaces\EncryptedNotepad2>go build -o myapp.exe -a
package github.com/ivoras/EncryptedNotepad2
imports fyne.io/fyne/v2/app
imports fyne.io/fyne/v2/internal/driver/glfw
imports fyne.io/fyne/v2/internal/driver/common
imports fyne.io/fyne/v2/internal/painter/gl
imports github.com/go-gl/gl/v2.1/gl: build constraints exclude all Go files in C:\Users\isaac\go\pkg\mod\github.com\go-gl\gl@v0.0.0-20231021071112-07e5d0ea2e71\v2.1\gl
C:\Users\isaac\Workspaces\EncryptedNot
I also attempted to do the same in linux hoping perhaps it would compile for windows
builder@DESKTOP-QADGF36:~/Workspaces/EncryptedNotepad2$ env GOOS=windows GOARCH=amd64 go build -o encnp2.exe
go: downloading github.com/tevino/abool v1.2.0
package github.com/ivoras/EncryptedNotepad2
imports fyne.io/fyne/v2/app
imports fyne.io/fyne/v2/internal/driver/glfw
imports fyne.io/fyne/v2/internal/driver/common
imports fyne.io/fyne/v2/internal/painter/gl
imports github.com/go-gl/gl/v2.1/gl: build constraints exclude all Go files in /home/builder/go/pkg/mod/github.com/go-gl/gl@v0.0.0-20211210172815-726fda9656d6/v2.1/gl
Usage
I’ll save a text doc to my windows Documents folder
We need to use a password
If we open the file now in Windows, we can see it is encrypted
We can also see this using linux
$ cat /mnt/c/Users/isaac/Documents/test.txt
-----BEGIN PGP MESSAGE-----
Version: GopenPGP 2.7.5
Comment: https://gopenpgp.org
wy4ECQMISYzoGyjEz/jgLfkXZkhmXtCdgWdisQ1NrSKoeOxQT9/n/o6eP6C1dPx9
0kABYNDIiizXTL8hhAkbVkT1epaF4SlVavbUguoazczZ+6y9d+qL0L8xK65DIzFg
ntUxvKSKvLZFTb5H/vK32iJ6
=36Qn
-----END PGP MESSAGE-----
However, I cannot seem to find it when i want to open
If we save with the .asc
extension, then we can find it
I can then enter the password I used when I saved it
Then I see the contents
and if I enter the wrong password
AzDO
I can do a similar build in AzDO
jobs:
- job: Job_1
displayName: Agent job 1
pool:
vmImage: ubuntu-latest
steps:
- checkout: self
clean: true
fetchTags: false
- task: Bash@3
displayName: Install X11
inputs:
targetType: inline
script: >-
# Write your commands here
sudo apt update
sudo apt install -y libxft-dev libxcursor-dev libxrandr-dev libxinerama-dev libxi-dev mesa-common-dev gcc libgl1-mesa-dev xorg-dev
- task: GoTool@0
displayName: Use Go 1.22.4
inputs:
version: 1.22.4
- task: Go@0
displayName: go get
- task: Go@0
displayName: go build
inputs:
command: build
- task: PublishPipelineArtifact@1
displayName: Publish Pipeline Artifact
inputs:
path: $(Pipeline.Workspace)/s
artifactName: EncryptedNotepad2
I can now see a compiled artifact
I’ll now try going to a different host and download the binary to test.
I get a seg fault. Even when adding all the build libraries from the other
$ /mnt/c/Users/isaac/Downloads/EncryptedNotepad2
2024/06/06 19:36:40 Fyne error: Unable to connect to session D-Bus
2024/06/06 19:36:40 Cause: dial unix /run/user/1000/bus: connect: no such file or directory
2024/06/06 19:36:40 At: /home/vsts/go/pkg/mod/fyne.io/fyne/v2@v2.4.5/app/app_xdg.go:40
2024/06/06 19:36:40 Fyne error: Unable to connect to session D-Bus
2024/06/06 19:36:40 Cause: dial unix /run/user/1000/bus: connect: no such file or directory
2024/06/06 19:36:40 At: /home/vsts/go/pkg/mod/fyne.io/fyne/v2@v2.4.5/app/app_xdg.go:177
Segmentation fault
I question the WSL on this host, however, as even a local compile segfaults
go: downloading github.com/jsummers/gobmp v0.0.0-20151104160322-e2ba15ffa76e
go: downloading github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6
go: downloading golang.org/x/net v0.17.0
builder@LuiGi:~/Workspaces/EncryptedNotepad2$ ls
ABOUT.md Makefile go.sum handle_savefileas.go pandoc.css
EncryptedNotepad2 README.md handle_help.go icons screenshot.png
Icon.png TODO.md handle_newfile.go icons.go version.go
LICENSE consts.go handle_openfile.go main.go widget_customentry.go
LICENSE_addendum go.mod handle_savefile.go main_window.go
builder@LuiGi:~/Workspaces/EncryptedNotepad2$ ./EncryptedNotepad2
2024/06/06 19:43:38 Fyne error: Unable to connect to session D-Bus
2024/06/06 19:43:38 Cause: dial unix /run/user/1000/bus: connect: no such file or directory
2024/06/06 19:43:38 At: /home/builder/go/pkg/mod/fyne.io/fyne/v2@v2.4.5/app/app_xdg.go:40
2024/06/06 19:43:38 Fyne error: Unable to connect to session D-Bus
2024/06/06 19:43:38 Cause: dial unix /run/user/1000/bus: connect: no such file or directory
2024/06/06 19:43:38 At: /home/builder/go/pkg/mod/fyne.io/fyne/v2@v2.4.5/app/app_xdg.go:177
Segmentation fault
builder@LuiGi:~/Workspaces/EncryptedNotepad2$
I rebooted and still no go, but I know X works as i can fire up xeyes
I guess it just works sometimes
builder@LuiGi:~/Workspaces/EncryptedNotepad2$ ./EncryptedNotepad2
2024/06/06 19:50:10 Fyne error: Unable to connect to session D-Bus
2024/06/06 19:50:10 Cause: dial unix /run/user/1000/bus: connect: no such file or directory
2024/06/06 19:50:10 At: /home/builder/go/pkg/mod/fyne.io/fyne/v2@v2.4.5/app/app_xdg.go:40
2024/06/06 19:50:10 Fyne error: Unable to connect to session D-Bus
2024/06/06 19:50:10 Cause: dial unix /run/user/1000/bus: connect: no such file or directory
2024/06/06 19:50:10 At: /home/builder/go/pkg/mod/fyne.io/fyne/v2@v2.4.5/app/app_xdg.go:177
Segmentation fault
builder@LuiGi:~/Workspaces/EncryptedNotepad2$ sudo ./EncryptedNotepad2
[sudo] password for builder:
Segmentation fault
Cryptpad
I found one more option I wanted to explore today, CryptPad. While the installation guide really prefers a server setup with two domains, it does list Docker steps as well.
Just as I was about to work those over, I found their helm repo which should greatly simplify things.
I’ll start by creating a namespace and installing the chart from the OCI location
$ kubectl create ns cryptpad
namespace/cryptpad created
$ helm install cryptpad -n cryptpad oci://ghcr.io/cryptpad/helm/cryptpad
Pulled: ghcr.io/cryptpad/helm/cryptpad:0.0.19
Digest: sha256:fe74a6329afd5c61b8f2e75580a6c8d5ee22de0c2460c35966d46050457e4315
NAME: cryptpad
LAST DEPLOYED: Fri Jun 7 05:45:23 2024
NAMESPACE: cryptpad
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods --namespace cryptpad -l "app.kubernetes.io/name=cryptpad,app.kubernetes.io/instance=cryptpad" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace cryptpad $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace cryptpad port-forward $POD_NAME 8080:$CONTAINER_PORT
I followed those steps and brought up the WebUI
I’ll then just create an account
We get a spinney icon as it does some password hashing
(spoiler: nothing will happen due to CORS issues we’ll discuss in a moment)
It stayed there for way too long. Perhaps it created it but doesn’t refresh right when port-forwarding?
Trying to login with it didn’t work
Ingress
Next, I’ll create an ingress A Record in Azure DNS
$ 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 cryptpad
{
"ARecords": [
{
"ipv4Address": "75.73.224.240"
}
],
"TTL": 3600,
"etag": "eb5153a7-9058-486e-8adf-c0e3716b57ef",
"fqdn": "cryptpad.tpk.pw.",
"id": "/subscriptions/d955c0ba-13dc-44cf-a29a-8fed74cbb22d/resourceGroups/idjdnsrg/providers/Microsoft.Network/dnszones/tpk.pw/A/cryptpad",
"name": "cryptpad",
"provisioningState": "Succeeded",
"resourceGroup": "idjdnsrg",
"targetResource": {},
"type": "Microsoft.Network/dnszones/A"
}
I noted the service is on 80 and 83. I’ll look at just the primary
$ kubectl get svc -n cryptpad
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
cryptpad ClusterIP 10.43.36.139 <none> 80/TCP,83/TCP 6m57s
# From service
ports:
- name: http
port: 80
protocol: TCP
targetPort: http
- name: ws
port: 83
protocol: TCP
targetPort: ws
# From pod
ports:
- containerPort: 3000
name: http
protocol: TCP
- containerPort: 3003
name: ws
protocol: TCP
I’ll now create an ingres, but I’m only servicing port 80
$ cat cryptpad.ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
cert-manager.io/cluster-issuer: azuredns-tpkpw
ingress.kubernetes.io/ssl-redirect: "true"
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.org/websocket-services: cryptpad
name: cryptpad-ingress
namespace: cryptpad
spec:
rules:
- host: cryptpad.tpk.pw
http:
paths:
- backend:
service:
name: cryptpad
port:
number: 80
path: /
pathType: Prefix
tls:
- hosts:
- cryptpad.tpk.pw
secretName: cryptpad-tls
$ kubectl apply -f cryptpad.ingress.yaml
ingress.networking.k8s.io/cryptpad-ingress created
I’ll wait on the cert to get created
builder@DESKTOP-QADGF36:~/Workspaces/EncryptedNotepad2$ kubectl get cert -n cryptpad
NAME READY SECRET AGE
cryptpad-tls False cryptpad-tls 19s
builder@DESKTOP-QADGF36:~/Workspaces/EncryptedNotepad2$ kubectl get cert -n cryptpad
NAME READY SECRET AGE
cryptpad-tls False cryptpad-tls 44s
builder@DESKTOP-QADGF36:~/Workspaces/EncryptedNotepad2$ kubectl get cert -n cryptpad
NAME READY SECRET AGE
cryptpad-tls False cryptpad-tls 72s
builder@DESKTOP-QADGF36:~/Workspaces/EncryptedNotepad2$ kubectl get cert -n cryptpad
NAME READY SECRET AGE
cryptpad-tls True cryptpad-tls 86s
I’ll try and register again
It seems to be the same hung screen as before and nothing really shows in the logs
Someone said to check the browser output for errors in a GH issue
And indeed, we can see we are back to COORs issues
register/:1 Access to fetch at 'http://localhost:3000/block/dg/dg99pJJIIIcsp5EZiR4QEJgjxc571aQ-AisZH+QJAkA=' from origin 'https://cryptpad.tpk.pw' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Digging into the docs, I suspect it’s a lack of setting the origin configs
I’ll try the quick approach of just upgrading my chart with the new values
2$ helm upgrade cryptpad -n cryptpad --set application_config.httpUnsafeOrigin='https://cryptpad.tpk.pw' --set application_config.httpSafeOrigin='https://cryptpad.tpk.pw' oci://ghcr.io/cryptpad/helm/cryptpad
Pulled: ghcr.io/cryptpad/helm/cryptpad:0.0.19
Digest: sha256:fe74a6329afd5c61b8f2e75580a6c8d5ee22de0c2460c35966d46050457e4315
Release "cryptpad" has been upgraded. Happy Helming!
NAME: cryptpad
LAST DEPLOYED: Fri Jun 7 06:09:37 2024
NAMESPACE: cryptpad
STATUS: deployed
REVISION: 2
TEST SUITE: None
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods --namespace cryptpad -l "app.kubernetes.io/name=cryptpad,app.kubernetes.io/instance=cryptpad" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace cryptpad $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace cryptpad port-forward $POD_NAME 8080:$CONTAINER_PORT
The values are set, but i’m still seeing ‘localhost:3000’ as the origin
I also tried (with the same result)
$ helm upgrade cryptpad -n cryptpad --set application_config.AppConfig.httpUnsafeOrigin='https://cryptpad.tpk.pw' --set application_config
.AppConfig.httpSafeOrigin='https://cryptpad.tpk.pw' oci://ghcr.io/cryptpad/helm/cryptpad
But still CORS errors
Hopping into the container, I see it’s rather stuck with that value as it’s hard-coded
cryptpad@cryptpad-0:~/config$ cat config.js
/* globals module */
module.exports = {
httpUnsafeOrigin: 'http://localhost:3000',
httpSafeOrigin: 'http://localhost:3000',
adminKeys: [],
archivePath: "./data/archive",
blobPath: "./blob",
blobStagingPath: "./data/blobstage",
blockPath: "./block",
decreePath: "./data/decrees",
filePath: "./datastore/",
httpAddress: "0.0.0.0",
installMethod: "helm-docker",
logFeedback: "false",
logLevel: "info",
logPath: "./data/logs",
logToStdout: "false",
pinPath: "./data/pins",
taskPath: "./data/tasks",
verbose: "false",
};
My last shot was to try some local values files
$ cat values.yaml
config:
httpUnsafeOrigin: "https://cryptpad.tpk.pw"
httpSafeOrigin: "https://cryptpad.tpk.pw"
# https://docs.cryptpad.org/en/admin_guide/customization.html#application-config
application_config:
httpUnsafeOrigin: "https://cryptpad.tpk.pw"
httpSafeOrigin: "https://cryptpad.tpk.pw"
$ helm upgrade cryptpad -n cryptpad -f ./values.yaml oci://ghcr.io/cryptpad/helm/cryptpad
Pulled: ghcr.io/cryptpad/helm/cryptpad:0.0.19
Digest: sha256:fe74a6329afd5c61b8f2e75580a6c8d5ee22de0c2460c35966d46050457e4315
Release "cryptpad" has been upgraded. Happy Helming!
NAME: cryptpad
LAST DEPLOYED: Fri Jun 7 06:20:39 2024
NAMESPACE: cryptpad
STATUS: deployed
REVISION: 4
TEST SUITE: None
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods --namespace cryptpad -l "app.kubernetes.io/name=cryptpad,app.kubernetes.io/instance=cryptpad" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace cryptpad $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace cryptpad port-forward $POD_NAME 8080:$CONTAINER_PORT
I watched it rotate
builder@DESKTOP-QADGF36:~/Workspaces/EncryptedNotepad2$ kubectl get pods -n cryptpad
NAME READY STATUS RESTARTS AGE
cryptpad-0 1/1 Terminating 0 4m7s
builder@DESKTOP-QADGF36:~/Workspaces/EncryptedNotepad2$ kubectl get pods -n cryptpad
No resources found in cryptpad namespace.
builder@DESKTOP-QADGF36:~/Workspaces/EncryptedNotepad2$ kubectl get pods -n cryptpad
NAME READY STATUS RESTARTS AGE
cryptpad-0 0/1 Init:0/1 0 2s
builder@DESKTOP-QADGF36:~/Workspaces/EncryptedNotepad2$ kubectl get pods -n cryptpad
NAME READY STATUS RESTARTS AGE
cryptpad-0 0/1 Running 0 5s
builder@DESKTOP-QADGF36:~/Workspaces/EncryptedNotepad2$ kubectl get pods -n cryptpad
NAME READY STATUS RESTARTS AGE
cryptpad-0 0/1 Running 0 11s
builder@DESKTOP-QADGF36:~/Workspaces/EncryptedNotepad2$ kubectl get pods -n cryptpad
NAME READY STATUS RESTARTS AGE
cryptpad-0 1/1 Running 0 16s
Thisis the first time I see show the proper url
This time it worked!
I’ll do a new Rich Text document
And I’ll give it a unique password
I’ll write some kind of contentious doc
I can then go back and see the file
If I’m logged in, I can double click to re-open it.
However, if I share the URL, then I need that password
Which opens a doc read-only
I need to see if this survives a pod cycling. I do see evidence of PVCs
builder@DESKTOP-QADGF36:~/Workspaces/EncryptedNotepad2$ kubectl get pvc -n cryptpad
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
cryptpad-blob-cryptpad-0 Bound pvc-aad32b6a-821b-43be-97b7-ac465c6d50fa 100Mi RWO local-path 54m
cryptpad-block-cryptpad-0 Bound pvc-9067b0e2-9d28-4536-954f-25ee5b83b4ac 100Mi RWO local-path 54m
cryptpad-data-cryptpad-0 Bound pvc-53a02151-d362-4d93-a1b0-0092477d7e64 100Mi RWO local-path 54m
cryptpad-datastore-cryptpad-0 Bound pvc-0708653b-8e0d-4f4d-ad8f-017bb03b03a2 100Mi RWO local-path 54m
I cycled the pod
builder@DESKTOP-QADGF36:~/Workspaces/EncryptedNotepad2$ kubectl get po -n cryptpad
NAME READY STATUS RESTARTS AGE
cryptpad-0 1/1 Running 0 14m
builder@DESKTOP-QADGF36:~/Workspaces/EncryptedNotepad2$ kubectl delete po cryptpad-0 -n cryptpad
pod "cryptpad-0" deleted
builder@DESKTOP-QADGF36:~/Workspaces/EncryptedNotepad2$ kubectl get po -n cryptpad
NAME READY STATUS RESTARTS AGE
cryptpad-0 1/1 Running 0 16s
I then checked the doc and it was live and working
Let’s look at creating a code document and sharing it as a view-once destructive link
Summary
Today we looked at Netbox for managing a Data Center and some of its features. We looked into EncryptedNotepad2 which is a Go-lang based app that seems to compile for Linux without issue but only ran on one of my two WSLs. I couldn’t get it to compile for Windows (and wasn’t willing to spend $25 to see if it had a Win binary). Lastly, we looked at setting up CryptPad which is a web-based encrypted doc system that allows sharing.
I likely won’t use Netbox as I really have no need for it and I would more likely re-install PHPIPAM which can scan my network to add IPs. I do plan to keep CryptPad in my cluster as that is a really nice way to create and share docs and secrets.