Heard about the latest passsword breach (since lunch)? HaveYouBeenPowned lately? Passwords are broken , and as the amount of sites for which you need to store credentials grows exponetially, so does the risk of using a common password.
This is a companion discussion topic for the original entry at https://geek-cookbook.funkypenguin.co.nz/recipes/bitwarden/
sorg
May 15, 2019, 5:06pm
2
Hi!
I will give this recipe a try. I have been using the chrome/google password manager for a couple of years. Probably not my smartest move
In you docker compose file, you are refering to an environment file:
/var/data/config/bitwarden/bitwarden.env
But you do not specify its content.
What should we do with this file ?
sorg
May 15, 2019, 6:54pm
3
OK, found everything i need to know here:
Wow, that’s brilliant. I wasn’t aware of all that, I’ll add it to the recipe, thanks!
sorg
May 16, 2019, 6:24am
5
I am really impressed by bitwarden by the way: Much better than lastpass, and as convenient as chrome password manager once the chrome extension and android app are installed.
The integration of TOTP to each account is a great improvement.
I have not been able to use my U2F usb key to secure the access to bitwarden at this stage. not sure why. The key seems not detected by the browser even if it works well on other website.
The 2FA authentification with authenticator/authy works very well though.
Regarding the env variables, I am using myself config fully centralized on portainer: i create app template on github that are called by Portainer to create the stack.
For obvious safety reasons , Some critical parameters are set as variables define within portainer.
example:
Works like a charm but i am also considering using the config and secrets mechanism of docker through portainer.
I agree, BitWarden is really nicely polished. If I wasn’t already invested in the 1Password world, along with the rest of the family, I’d be a convert
Agreed. I like BitWarden, but have recently gotten everyone migrated to 1Password.
Hi @sorg ! I also could not get U2F working with my Yubikey. However, I was able to make Yubico OTP work which requires setting these two environment variables:
YUBICO_CLIENT_ID
YUBICO_SECRET_KEY
These are obtained by signing up for YubiCloud at this URL: Yubico API key signup
After setup, I can even use the YubiKey 5 NFC and hold it to the back of my iPhone to provide a secure hardware second factor to BitWarden on the iPhone. It’s pretty sweet and I wish that 1Password supported it, but they have been reticent almost to the point of obstinate about not doing it for some reason.
Hi! I note you are looking for recipes for Kubernetes, well, I have Bitwarden for you
It’s not a helm chart, but I have a basic Kubernetes YAML file that sets up a configmap for environment variables, and a deployment with all containers in a single pod so they can communicate with each other via localhost. I used a specific environment variable in several containers - ASPNETCORE_URLS, to have each web component listen on a different port to 5000. The ingress configuration is for HAProxy, but shouldn’t need much effort to convert to nginx/traefik.
The prerequisites are the same - run the bitwarden script to setup the directory structure, then set the path on the volumeMounts in the deployment. Replace the usernames, passwords, IDs and keys with your own from the global.env, uid.env and override files.
Hope this helps!
apiVersion: v1
kind: ConfigMap
metadata:
name: bitwarden-config
namespace: default
data:
ACCEPT_EULA: "Y"
MSSQL_PID: "Express"
SA_PASSWORD: "<sa_password>"
ASPNETCORE_ENVIRONMENT: "Production"
globalSettings__selfHosted: "true"
globalSettings__baseServiceUri__vault: "http://bitwarden.mydomain.com"
globalSettings__baseServiceUri__api: "http://bitwarden.mydomain.com/api"
globalSettings__baseServiceUri__identity: "http://bitwarden.mydomain.com/identity"
globalSettings__baseServiceUri__admin: "http://bitwarden.mydomain.com/admin"
globalSettings__baseServiceUri__notifications: "http://bitwarden.mydomain.com/notifications"
globalSettings__baseServiceUri__internalNotifications: "http://localhost:5006"
globalSettings__baseServiceUri__internalAdmin: "http://localhost:5004"
globalSettings__baseServiceUri__internalIdentity: "http://localhost:5003"
globalSettings__baseServiceUri__internalApi: "http://localhost:5002"
globalSettings__baseServiceUri__internalVault: "http://localhost:5000"
globalSettings__pushRelayBaseUri: "https://push.bitwarden.com"
globalSettings__installation__identityUri: "https://identity.bitwarden.com"
globalSettings__sqlServer__connectionString: "Data Source=tcp:localhost,1433;Initial Catalog=vault;Persist Security Info=False;User ID=sa;Password=<password>;MultipleActiveResultSets=False;Connect Timeout=30;Encrypt=True;TrustServerCertificate=True"
globalSettings__identityServer__certificatePassword: "<cert pwd>"
globalSettings__attachment__baseDirectory: "/etc/bitwarden/core/attachments"
globalSettings__attachment__baseUrl: "http://bitwarden.mydomain.com/attachments"
globalSettings__dataProtection__directory: "/etc/bitwarden/core/aspnet-dataprotection"
globalSettings__logDirectory: "/etc/bitwarden/logs"
globalSettings__licenseDirectory: "/etc/bitwarden/core/licenses"
globalSettings__internalIdentityKey: "<idkey>"
globalSettings__duo__aKey: "<duo_akey>"
globalSettings__installation__id: "<install_id>"
globalSettings__installation__key: "<install_key>"
globalSettings__yubico__clientId: "<yubico_id>"
globalSettings__yubico__key: "<yubico_key>"
globalSettings__mail__replyToEmail: "[email protected] "
globalSettings__mail__smtp__host: "smtp.mydomain.com"
globalSettings__mail__smtp__port: "587"
globalSettings__mail__smtp__ssl: "false"
globalSettings__mail__smtp__username: "username"
globalSettings__mail__smtp__password: "password"
globalSettings__disableUserRegistration: "false"
adminSettings__admins:
LOCAL_UID: "UID"
LOCAL_GID: "GID"
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
k8s.app: bitwarden
name: bitwarden
namespace: default
spec:
selector:
matchLabels:
k8s.app: bitwarden
template:
metadata:
labels:
k8s.app: bitwarden
spec:
containers:
- image: bitwarden/mssql:1.30.4
name: bitwarden-mssql
envFrom:
- configMapRef:
name: bitwarden-config
ports:
- containerPort: 1433
protocol: TCP
volumeMounts:
- mountPath: /var/opt/mssql/data
name: mssql-data
- mountPath: /var/opt/mssql/log
name: mssql-logs
- mountPath: /etc/bitwarden/mssql/backups
name: mssql-backup
- image: bitwarden/web
name: bitwarden-web
envFrom:
- configMapRef:
name: bitwarden-config
ports:
- containerPort: 5000
protocol: TCP
volumeMounts:
- mountPath: /etc/bitwarden/web
name: web-data
- image: bitwarden/attachments:1.30.4
name: bitwarden-attachments
envFrom:
- configMapRef:
name: bitwarden-config
env:
- name: ASPNETCORE_URLS
value: http://+:5001
ports:
- containerPort: 5001
protocol: TCP
volumeMounts:
- mountPath: /etc/bitwarden/core/attachments
name: attachment-core
- image: bitwarden/api:1.30.4
name: bitwarden-api
envFrom:
- configMapRef:
name: bitwarden-config
env:
- name: ASPNETCORE_URLS
value: http://+:5002
ports:
- containerPort: 5002
protocol: TCP
volumeMounts:
- mountPath: /etc/bitwarden/core
name: bitwarden-core
- mountPath: /etc/bitwarden/ca-certificates
name: cacerts
- mountPath: /etc/bitwarden/logs
name: api-logs
- image: bitwarden/identity:1.30.4
name: bitwarden-identity
envFrom:
- configMapRef:
name: bitwarden-config
env:
- name: ASPNETCORE_URLS
value: http://+:5003
ports:
- containerPort: 5003
protocol: TCP
volumeMounts:
- mountPath: /etc/bitwarden/identity
name: id-core
- mountPath: /etc/bitwarden/core
name: bitwarden-core
- mountPath: /etc/bitwarden/ca-certificates
name: cacerts
- mountPath: /etc/bitwarden/logs
name: id-logs
- image: bitwarden/admin:1.30.4
name: bitwarden-admin
envFrom:
- configMapRef:
name: bitwarden-config
env:
- name: ASPNETCORE_URLS
value: http://+:5004
ports:
- containerPort: 5004
protocol: TCP
volumeMounts:
- mountPath: /etc/bitwarden/core
name: bitwarden-core
- mountPath: /etc/bitwarden/ca-certificates
name: cacerts
- mountPath: /etc/bitwarden/logs
name: admin-logs
- image: bitwarden/icons:1.30.4
name: bitwarden-icons
envFrom:
- configMapRef:
name: bitwarden-config
env:
- name: ASPNETCORE_URLS
value: http://+:5005
ports:
- containerPort: 5005
protocol: TCP
volumeMounts:
- mountPath: /etc/bitwarden/ca-certificates
name: cacerts
- mountPath: /etc/bitwarden/logs
name: icon-logs
- image: bitwarden/notifications:1.30.4
name: bitwarden-notifications
envFrom:
- configMapRef:
name: bitwarden-config
env:
- name: ASPNETCORE_URLS
value: http://+:5006
ports:
- containerPort: 5006
protocol: TCP
volumeMounts:
- mountPath: /etc/bitwarden/ca-certificates
name: cacerts
- mountPath: /etc/bitwarden/logs
name: notify-logs
volumes:
- hostPath:
path: /path/to/bwdata/mssql/data
name: mssql-data
- hostPath:
path: /path/to/bwdata/logs/mssql
name: mssql-logs
- hostPath:
path: /path/to/bwdata/mssql/backups
name: mssql-backup
- hostPath:
path: /path/to/bwdata/web
name: web-data
- hostPath:
path: /path/to/bwdata/core/attachments
name: attachment-core
- hostPath:
path: /path/to/bwdata/logs/api
name: api-logs
- hostPath:
path: /path/to/bwdata/identity
name: id-core
- hostPath:
path: /path/to/bwdata/core
name: bitwarden-core
- hostPath:
path: /path/to/bwdata/ca-certificates
name: cacerts
- hostPath:
path: /path/to/bwdata/logs/identity
name: id-logs
- hostPath:
path: /path/to/bwdata/logs/admin
name: admin-logs
- hostPath:
path: /path/to/bwdata/logs/icons
name: icon-logs
- hostPath:
path: /path/to/bwdata/logs/notifications
name: notify-logs
---
apiVersion: v1
kind: Service
metadata:
labels:
k8s.app: bitwarden
name: bitwarden
namespace: default
spec:
ports:
- name: web
port: 5000
protocol: TCP
targetPort: 5000
- name: attachments
port: 5001
protocol: TCP
targetPort: 5001
- name: api
port: 5002
protocol: TCP
targetPort: 5002
- name: identity
port: 5003
protocol: TCP
targetPort: 5003
- name: admin
port: 5004
protocol: TCP
targetPort: 5004
- name: icons
port: 5005
protocol: TCP
targetPort: 5005
- name: notifications
port: 5006
protocol: TCP
targetPort: 5006
selector:
k8s.app: bitwarden
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/config-backend: |
http-response set-header Referrer-Policy same-origin
http-response set-header X-Content-Type-Options nosniff
http-response set-header X-XSS-Protection "1; mode=block"
http-response set-header Content-Security-Policy "default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://haveibeenpwned.com https://www.gravatar.com; child-src 'self' https://*.duosecurity.com; frame-src 'self' https://*.duosecurity.com; connect-src 'self' wss://bitwarden.mydomain.com https://api.pwnedpasswords.com https://twofactorauth.org; object-src 'self' blob:;"
http-response set-header X-Frame-Options SAMEORIGIN
http-response set-header X-Robots-Tag "noindex, nofollow"
http-response set-header Content-Type application/fido.trusted-apps+json if { var(txn.path) -m str /app-id.json }
ingress.kubernetes.io/secure-backends: "false"
ingress.kubernetes.io/ssl-passthrough: "false"
kubernetes.io/ingress.class: haproxy
name: bitwarden
namespace: default
spec:
rules:
- host: bitwarden.mydomain.com
http:
paths:
- path: /
backend:
serviceName: bitwarden
servicePort: 5000
tls:
- hosts:
- bitwarden.mydomain.com
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/config-backend: |
http-response set-header Referrer-Policy same-origin
http-response set-header X-Content-Type-Options nosniff
http-response set-header X-XSS-Protection "1; mode=block"
http-response set-header X-Frame-Options SAMEORIGIN
ingress.kubernetes.io/secure-backends: "false"
ingress.kubernetes.io/ssl-passthrough: "false"
kubernetes.io/ingress.class: haproxy
name: bitwarden-admin
namespace: default
spec:
rules:
- host: bitwarden.mydomain.com
http:
paths:
- path: /admin
backend:
serviceName: bitwarden
servicePort: 5004
tls:
- hosts:
- bitwarden.mydomain.com
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/config-backend: |
http-response set-header Referrer-Policy same-origin
http-response set-header X-Content-Type-Options nosniff
http-response set-header X-XSS-Protection "1; mode=block"
ingress.kubernetes.io/secure-backends: "false"
ingress.kubernetes.io/ssl-passthrough: "false"
ingress.kubernetes.io/rewrite-target: /
kubernetes.io/ingress.class: haproxy
name: bitwarden-api-id-icons
namespace: default
spec:
rules:
- host: bitwarden.mydomain.com
http:
paths:
- path: /api/
backend:
serviceName: bitwarden
servicePort: 5002
- path: /identity/
backend:
serviceName: bitwarden
servicePort: 5003
- path: /icons/
backend:
serviceName: bitwarden
servicePort: 5005
- path: /notifications/
backend:
serviceName: bitwarden
servicePort: 5006
- path: /attachments/
backend:
serviceName: bitwarden
servicePort: 5001
tls:
- hosts:
- bitwarden.mydomain.com
Wow, that’s amazing! Thank you, I’ll work on adding it to the cookbook. Any objections if I “helmify” it?
No objections, happy to help more people host it on K8s. I’d be interested to see the ingress definitions translated to traefik too. The difficult part was trawling through Bitwarden’s GitHub repo to see if there were any command line arguments etc. to change the port number of the .NET core services, turns out their Dockerfiles specified that environment variable so I was able to change that
Initially I was going to host each container in its own pod but that looked messy with more services etc., and it didn’t make sense as I couldn’t see one particular service requiring scaling over others.