57 KiB
title | description | sidebar_label | slug |
---|---|---|---|
Integrating Secrets | Discover how to leverage the incredibly useful but optional integrations that Install Doctor supports by integrating variables in the form of environment variables and encrypted secrets into your own custom fork. | Secrets | /customization/secrets |
Install Doctor implements many optional features that rely on user-specific variables. Most of these user-specific variables are API keys. To augment that capabilities of your device, Install Doctor can leverage API keys to many free and popular cloud services. These API keys, as well as other user-specific variables, can be utilized by defining them as environment variables prior to running the start script. It is also possible to encrypt and bundle some of these secrets into your own fork of the Install Doctor repository.
Environment Variables
The easiest way to get started with automating the Install Doctor provisioning process and leveraging optional features is to define user-specific variables as environment variables.
For instance, if you want to automate the provisioning process the first time you run the Install Doctor quick start script (without deep diving into all the variables yet), you can run the following (depending on your operating system):
Linux / macOS:
export HEADLESS_INSTALL=true
export SOFTWARE_GROUP=Standard-Desktop
export FULL_NAME="Joe Shmoe"
export PRIMARY_EMAIL="help@megabyte.space"
export PUBLIC_SERVICES_DOMAIN="megabyte.space"
export START_REPO=my-gh-user/my-fork-name
bash <(curl -sSL https://install.doctor/start)
Windows:
$env:HEADLESS_INSTALL = true
$env:SOFTWARE_GROUP = Standard-Desktop
$env:FULL_NAME = 'Joe Shmoe'
$env:PRIMARY_EMAIL = 'help@megabyte.space'
$env:PUBLIC_SERVICES_DOMAIN = 'megabyte.space'
$env:START_REPO = 'my-gh-user/my-fork-name'
iex ((New-Object System.Net.WebClient).DownloadString('https://install.doctor/windows'))
Qubes:
export HEADLESS_INSTALL=true
export SOFTWARE_GROUP=Standard-Desktop
export FULL_NAME="Joe Shmoe"
export PRIMARY_EMAIL="help@megabyte.space"
export PUBLIC_SERVICES_DOMAIN="megabyte.space"
export START_REPO=my-gh-user/my-fork-name
qvm-run --pass-io sys-firewall "curl -sSL https://install.doctor/qubes" > ~/setup.sh
bash ~/setup.sh
Running the blocks of code listed above will bypass the Install Doctor TUI prompt system, allowing a completely headless setup process for your device.
There are many other variables you can make use of which are detailed in one of the following sections below.
Encrypted Secrets
For added security and convienience, Install Doctor supports embedding your secret variables into your own fork of Install Doctor by encrypting them with the Chezmoi default encryption provider called Age. By using this method, you will no longer have to manage a long set of environment variables and you will be able to store your encrypted secrets in a public git that you can use to provision any of your devices.
The first thing you should do when leveraging your own Age encryption key in your own fork of Install Doctor is to delete all the keys stored in the home/.chezmoitemplates/secrets/
folder. If you do not do this, then Install Doctor will try unencrypting the test secrets using your key.
Creating an Age Key (Password Protected)
Install Doctor's default recommended encryption method involves:
- Creating a password protected Age encryption key
- Using the encryption key to encrypt your variables which are stored in
home/.chezmoitemplates/secrets/
To create an encryption key, first ensure Age is installed and available in your PATH (the quick start script will automatically install Homebrew / Age). With age
available from your terminal, run the following:
age-keygen | age -p > key.age
The output should look something like the following if you decided to forego creating a custom password:
Public key: age1wzpkjhk6jtgq2d3q97jdq7ptwpra7kdplnt38p5ruetcwfzahvps40l6a5
age: using autogenerated passphrase "act-client-permit-coil-clinic-cushion-wheat-beauty-ski-alarm"
Make note of the public key and your password. The public key should be added to the home/.chezmoi.yaml.tmpl
file under the age.recipient
key (just search for, "recipient" in the file). The key.age
file that was generated should be added to home/key.txt.age
. The quick start script that Install Doctor hosts expects the key to be stored in home/key.txt.age
.
With all of this done, you can commit your changes. Your key.txt.age
file is useless to anyone who does not know the password to decrypt it. The Install Doctor start script (that you can find on the homepage) will prompt you to decrypt the key.txt.age
file using your selected password and store it in the location specified in the home/.chezmoi.yaml.tmpl
file. For automation purposes, if you are using the default home/.chezmoi.yaml.tmpl
file settings, the unencrypted file is temporarily stored on the disk in the ~/.config/age/chezmoi.txt
location. This makes it easier to re-run the provisioning process and add new secrets to your custom fork. After you are done using the encryption key, you should delete the unencrypted Age key file stored at ~/.config/age/chezmoi.txt
.
Adding Secrets Using the Age Key
To add secrets to your custom fork, you need to ensure Chezmoi is configured to use the file stored in ~/.config/age/chezmoi.txt
that is decrypted using a password from the file stored in home/key.txt.age
of your custom fork. The easiest way to do this for the first time is to ensure the START_REPO
environment variable is pointing to your custom fork and run the quick start script:
Linux / macOS:
export START_REPO=my-gh-user/my-fork-name
bash <(curl -sSL https://install.doctor/start)
Windows:
$env:START_REPO = 'my-gh-user/my-fork-name'
iex ((New-Object System.Net.WebClient).DownloadString('https://install.doctor/windows'))
Qubes:
export START_REPO=my-gh-user/my-fork-name
qvm-run --pass-io sys-firewall "curl -sSL https://install.doctor/qubes" > ~/setup.sh
bash ~/setup.sh
Early in the provisioning process, the script will prompt you for your Age encryption passphrase. After this happens, you can CTRL+C out of the script and begin adding your encrypted secrets to your git repository fork.
With Chezmoi and Age configured, you can now begin encrypting all the pieces of data that you do not want to have to pass in as environment variables. You can also encrypt other things like SSH keys, GPG keys, etc.
Encrypting an API Key
To encrypt an API key, you would run:
echo "apikey-xXxxXxX" | chezmoi encrypt
The resulting text that outputs to the terminal would look something like this:
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCamNtb0pvOFRmYXRyNEhY
R1BpS09IYVBSSG83Rmh2MVJpdExKdjZrY2hVCmRmTTdjUDJyU2ZZK0NObmUwZ0dH
eGtFQUV6NXVPdjR1WFljNUkyczZuVjAKLS0tIDVTZDFPLytQVTJMNStUK21KYVF4
QVBhb0hIMG9tRjVuYWlHejN4cDJrQkkKTx7EQBmWL+0mXeaOOAtqo9rbJjWYx7mj
Jr4Trf/qfrmiDXX/
-----END AGE ENCRYPTED FILE-----
Copy the text including the lines that contain BEGIN AGE ENCRYPTED FILE
and END AGE ENCRYPTED FILE
and store them into the appropriate file nested inside home/.chezmoitemplates/secrets/
. You can determine the supported key file names by referring to the Supported Variables / Secrets Table below.
Encrypting a File
To encrypt an entire file (named myfile.ext
in the following example), you can run:
chezmoi encrypt myfile.ext
The resulting encrypted text can then be copied / pasted into the appropriate key file location. Supported targets are listed below in the Supported Variables / Secrets Table section.
Using GPG
If you prefer to use GPG instead of Age as your encryption mechanism, you can define this option in the home/.chezmoi.yaml.tmpl
file. For more details on this implementation, see the GPG page in the Chezmoi docs.
Users may want to do this so they can protect their secrets with hardware-backed encryption via devices like a YubiKey. For details on how to setup GPG with a YubiKey, refer to this guide.
Supported Variables / Secrets Table
The following table details all the custom variables supported by Install Doctor. The variable column denotes the name of the environment variable that can be specified to enable the automated deployment and the description details where the variable is used along with relevant details.
Unless otherwise specified in the description column, all of the variables in this chart can be stored as secrets by saving the encrypted secret environment variable in the home/.chezmoitemplates/secrets/
folder (with a file name equal to the environment variable name). So, if you wanted to saved your GITHUB_TOKEN
as an encrypted secret in your fork then you would encrypt following the instructions detailed above and then saved the encrypted secret in the home/.chezmoitemplates/secrets/GITHUB_TOKEN
location (e.g. echo "MY_GITHUB_API_TOKEN" | chezmoi encrypt > "home/.chezmoitemplates/secrets/GITHUB_TOKEN"
).
Variable | Description | |
---|---|---|
AGE_PASSWORD |
Automate the Chezmoi Age decryption process by passing in the passphrase for the key.txt.age file stored in the home/ folder (which is used to encrypt all your secrets). This variable can only be passed in as an environment variable. |
|
ANSIBLE_GALAXY_TOKEN |
Ansible Galaxy API token stored in ~/.config/shell/private.sh so developer API keys can be loaded by running source "~/.config/shell/private.sh" . |
|
ANSIBLE_VAULT_PASSWORD |
Ansible Vault password stored in ~/.config/shell/private.sh so developer API keys can be loaded by running source "~/.config/shell/private.sh" . |
|
APPLE_USERNAME |
Username of your Apple developer account which is assigned to the XCODES_USERNAME variable for automated use of the Xcodes CLI and app |
|
APPLE_PASSWORD |
Password of your Apple developer account which is assigned to the XCODES_PASSWORD variable for automated use of the Xcodes CLI and app |
|
ATUIN_EMAIL |
E-mail address used for registering with Atuin | |
ATUIN_PASSWORD |
Password used for registering with Atuin | |
ATUIN_USERNAME |
Username used for registering with Atuin | |
AWS_ACCESS_KEY_ID |
AWS access key ID (used for storing / retrieving from AWS Secret Manager which is used for headless Xcode installations / developer account authentications) | |
AWS_DEFAULT_REGION |
Default AWS region to use when region is not passed in via commands (e.g. us-east-1 ) |
|
AWS_SECRET_ACCESS_KEY |
AWS access key secret (used in conjunction with the AWS_ACCESS_KEY_ID ) |
|
CELL_PHONE_NUMBER |
Cell phone number you would like to receive Twilio notifications from via Apprise. The number should follow the format of 13332224444 where the 10-digit phone number is prefixed by the country code. |
|
CLOUDFLARE_API_KEY |
CloudFlare administration API key. Used by CloudFlare CLI. | |
CLOUDFLARE_ACCOUNT_ID |
The CloudFlare account ID | |
CLOUDFLARE_ORIGIN_CA_KEY |
The CloudFlare origin CA key (currently unused) | |
CLOUDFLARE_R2_ID and CLOUDFLARE_R2_ID_USER |
The CloudFlare R2 read / edit access key ID used for mounting S3-compliant buckets to various locations such as /mnt/s3-public , /mnt/s3-private , and ~/.local/mnt/s3 via rclone. The configuration files are located in ~/.config/rclone/ when CLOUDFLARE_R2_SECRET and .user.cloudflare.r2 in .chezmoi.yaml are defined. The key that ends in _USER is used for the ~/.local/mnt mount. |
|
CLOUDFLARE_R2_SECRET and CLOUDFLARE_R2_SECRET_USER |
The CloudFlare R2 read / edit secret access key used for mounting S3-compliant buckets to various locations such as /mnt/s3-public , /mnt/s3-private , and ~/.local/mnt/s3 via rclone. The configuration files are located in ~/.config/rclone/ when CLOUDFLARE_R2_ID and .user.cloudflare.r2 in .chezmoi.yaml are defined. The key that ends in _USER is used for the ~/.local/mnt mount. |
|
CLOUDFLARE_TEAMS_CLIENT_ID |
CloudFlare Teams client ID used to automatically connect to CloudFlare Teams network via warp-cli when CLOUDFLARE_TEAMS_CLIENT_SECRET is also available. You can acquire the secret from a CloudFlare Teams service token. See this article. |
|
CLOUDFLARE_TEAMS_CLIENT_SECRET |
CloudFlare Teams client secret used to automatically connect to CloudFlare Teams network via warp-cli when CLOUDFLARE_TEAMS_CLIENT_ID is also available. You can acquire the ID from a CloudFlare Teams service token. See this article. |
|
CLOUDFLARE_TEAMS_ORG |
The organization name used to connect to CloudFlare WARP Teams Zero Trust automatically. Used to populate the organization value referenced on this page. Can only be passed in as environment variable or hardcoded into home/.chezmoi.yaml.tmpl |
|
CLOUDSDK_CORE_PROJECT |
Injected into ~/.config/shell/private.sh and saved in your Chezmoi configuration. Can only be passed in as environment variable or hardcoded into home/.chezmoi.yaml.tmpl . |
|
DIGITALOCEAN_ACCESS_TOKEN |
DigitalOcean personal access token (generated via the Applications & API > Personal access tokens section). Used to connect to DigitalOcean-hosted Kubernetes cluster. | |
DOCKERHUB_USER |
DockerHub username which is used in combination with the DOCKERHUB_TOKEN to headlessly authenticate Docker Desktop with DockerHub |
|
DOCKERHUB_TOKEN |
DockerHub API token stored in ~/.config/shell/private.sh so developer API keys can be loaded by running source "~/.config/shell/private.sh" . |
|
ELEVENLABS_API_KEY |
API key for ElevenLabs which is used by ShortGPT | |
FIG_TOKEN |
Fig user API token used to headlessly login / authenticate with Fig. Token can be acquired on the token dashboard after logging in. | |
FULL_NAME |
Your full name used in things like the Git config and NPM config. This can be passed in as an environment variable or hardcoded into the home/.chezmoi.yaml.tmpl file. |
|
GCE_SERVICE_ACCOUNT_EMAIL |
Injected into ~/.config/shell/private.sh and saved in your Chezmoi configuration. Can only be passed in as environment variable or hardcoded into home/.chezmoi.yaml.tmpl . |
|
GITHUB_GIST_TOKEN |
GitHub token with gist permissions. Populates ~/.local/bin/gist so that the key does not have to be stored in the ~ directory. |
|
GITHUB_READ_TOKEN |
GitHub token with repository read permissions. Populates ~/.config/ghorg/conf.yaml so Ghorg can backup all of your GitHub repositories locally. |
|
GITHUB_TOKEN |
GitHub personal access token stored in ~/.config/shell/private.sh so developer API keys can be loaded by running source "~/.config/shell/private.sh" . |
|
GITLAB_READ_TOKEN |
GitLab token with repository read permissions. Populates ~/.config/ghorg/conf.yaml so Ghorg can backup all of your GitLab repositories locally. |
|
GITLAB_TOKEN |
GitLab personal access token stored in ~/.config/shell/private.sh so developer API keys can be loaded by running source "~/.config/shell/private.sh" . |
|
GITLAB_RUNNER_TOKEN_DARWIN |
GitLab runner token to use on macOS machines. | |
GITLAB_RUNNER_TOKEN_LINUX |
GitLab runner token to use on Linux machines. | |
GITLAB_RUNNER_TOKEN_WINDOWS |
GitLab runner token to use on Windows machines. | |
GMAIL_PASSWORD |
App password for GMail which is used as an outgoing SMTP service (for git e-mail). |
|
GOOGLE_SEARCH_API_KEY |
API key used by search-gpt available here. |
|
GOOGLE_SEARCH_ID |
Search engine ID for custom Google search engine utilized by search-gpt available here. |
|
HEADLESS_INSTALL |
Set to true if you would like all prompts to be bypassed. This variable can only be passed in as an environment variable. | |
HEROKU_API_KEY |
Heroku API token stored in ~/.config/shell/private.sh so developer API keys can be loaded by running source "~/.config/shell/private.sh" . |
|
HISHTORY_USER_SECRET |
User secret for synchronizing entries cataloged by Hishtory. | |
HOARD_API_TOKEN |
The API token for [Hoard]https://github.com/Hyde46/hoard). | |
HOST |
The hostname of the device. Used for a FQDN that resolves to the device when combined with the _ PUBLIC_SERVICES_DOMAIN . |
|
IFTTT_WEBHOOK_ID |
Webhook ID from the Maker webhook on IFTTT. This is used to integrate Apprise with IFTTT integration. | |
JUMPCLOUD_CONNECT_KEY |
JumpCloud device enrollment key. | |
KEYID |
Your GPG key ID available on the MIT or Ubuntu servers. During provisioning, the key will be imported and trusted with an elevated trust level. This can only be passed in as an environment variable or be hardcoded into the home/.chezmoi.yaml.tmpl file. |
|
MATRIX_PASSWORD |
Password for user account for matrix.org through Element. Used to integrate Matrix chatting with Apprise. | |
MATRIX_USERNAME |
Username for user account for matrix.org through Element. Used to integrate Matrix chatting with Apprise. | |
NETDATA_ROOM |
Netdata Cloud room ID to assign the device to. Requires NETDATA_TOKEN to also be defined. |
|
NETDATA_TOKEN |
Netdata Cloud API token to use when enrolling. Requires NETDATA_ROOM to also be defined. |
|
NGINX_AMPLIFY_API_KEY |
If NGINX is installed on the system, then this key will be used to join the NGINX Amplify cloud service. | |
NGROK_AUTH_TOKEN |
Populates Ngrok token in ~/.config/ngrok/ngrok.yml which allows you to use logged-in-only Ngrok services |
|
NO_RESTART |
Prevents computer from automatically restarting. This may interfere with system updates. | |
NPM_TOKEN |
NPM API token stored in ~/.config/shell/private.sh so developer API keys can be loaded by running source "~/.config/shell/private.sh" . |
|
OPENAI_API_KEY |
OpenAI API key available in the OpenAPI account settings manager. Used for OpenCommit (CLI that automatically generates commit messages). | |
OVPN_PASSWORD |
The OpenVPN password to apply to VPN profiles located at ~/.config/vpn/*.ovpn (e.g. encrypted ProtonVPN OpenVPN profiles). OVPN_USERNAME must also be defined. |
|
OVPN_USERNAME |
The OpenVPN username to apply to VPN profiles located at ~/.config/vpn/*.ovpn (e.g. encrypted ProtonVPN OpenVPN profiles). OVPN_PASSWORD must also be defined. |
|
OPENWEATHERMAP_API_KEY |
Free API key retrieved from OpenWeatherMap which powers the wego terminal weather application |
|
PORTAINER_BUSINESS_LICENSE |
Portainer business license key (free for up to 5 nodes) | |
PRIMARY_EMAIL |
Your primary e-mail address used in things like the Git config and NPM config. You must pass this as an environment variable or hardcode it into the home/.chezmoi.yaml.tmpl file. |
|
PUBLIC_SERVICES_DOMAIN |
The CloudFlare domain that you would like to use for CloudFlare DNS integration features. Can only be passed in as an environment variable. | |
PYPI_TOKEN |
PyPi.org API token stored in ~/.config/shell/private.sh |
|
REDDIT_APP_ID |
Application ID for Reddit app created according to the Apprise integration documentation. | |
REDDIT_APP_SECRET |
Application secret for Reddit app created according to the Apprise integration documentation. | |
REDDIT_PASSWORD |
Password for the Reddit developer account linked to the Reddit app created according to the Apprise integration documentation. | |
REDDIT_USERNAME |
Username for the Reddit developer account linked to the Reddit app created according to the Apprise integration documentation. | |
REPLICATE_API_KEY |
Replicate API key (used for AgentGPT) | |
RESTIC_PASSWORD |
Password used to encrypt user-level Restic backups (leveraged by autorestic ). This includes $HOME directory backups and application data backups. |
|
RESTIC_SYSTEM_PASSWORD |
Password used to encrypt system-level Restic backups (leveraged by autorestic ). This includes Docker volume backups and any other types of backups that might require sudo privileges. |
|
RESTRICTED_ENVIRONMENT |
Set to true if you are setting up a device that should not use sudo / administrator privileges. This can only be specified as an environment variable. This feature is a WIP. Pull requests welcome. |
|
SAMBA_NETBIOS_NAME |
NetBIOS name to use with Samba. Default value is the same value as the HOSTNAME variable. Can only be specified as an environment variable. |
|
SAMBA_WORKGROUP |
Samba workgroup name. Default value is BETELGEUSE . Can only be specified as an environment variable. |
|
SENDGRID_API_KEY |
SendGrid API token with the "Mail" permission. Used for sending mail with Postfix. | |
SERP_API_KEY |
API key for Serper.dev (used by AgentGPT) | |
SFTPGO_DEFAULT_ADMIN_PASSWORD |
Password for default admin user that can login to the SFTPGo web interface. | |
SFTPGO_DEFAULT_ADMIN_USERNAME |
Username for default admin user that can login to the SFTPGo web interface. | |
SLACK_API_TOKEN |
Slack API personal access token that populates ~/.config/slack-term/config so that you can use Slack from your terminal with slack-term. |
|
SLACK_BOT_USER_OAUTH_TOKEN |
Slack bot OAuth token. Used by Apprise Slack integration so that user can post to Slack (with support for attachments) from the CLI. | |
SNAPCRAFT_EMAIL |
Snapcraft.io e-mail address associated with the SNAPCRAFT_MACAROON and SNAPCRAFT_UNBOUND_DISCHARGE (detailed below). Stored in ~/.config/shell/private.sh so developer API credentials can be loaded by running source "~/.config/shell/private.sh" . *Can only be included as an environment variable or hardcoded into home/.chezmoi.yaml.tmpl . |
|
SNAPCRAFT_MACAROON |
Snapcraft.io authentication variable stored in ~/.config/shell/private.sh so developer API keys can be loaded by running source "~/.config/shell/private.sh" . |
|
SNAPCRAFT_UNBOUND_DISCHARGE |
Snapcraft.io authentication variable stored in ~/.config/shell/private.sh so developer API keys can be loaded by running source "~/.config/shell/private.sh" . |
|
SOFTWARE_GROUP |
Should be equal to only of the software lists defined in home/.chezmoidata.yaml (see the Customization page for more details). |
|
START_REPO |
Set to your GitHub username (if your fork is named install.doctor ) to be able to provision your device with the one-liner outlined on the homepage. You can also specify any GitHub project by setting this equal to GITHUB_USERNAME/PROJECT_NAME or a full git address (e.g. git@gitlab.com:megabyte-labs/install.doctor ). This can only be passed in as an environment variable. |
|
SUDO_PASSWORD |
Provide the sudo / administrator password to completely automate sudo password input. This is required on for automated deployments where the user running the script has a sudo password. | |
SURGE_LOGIN |
The e-mail address associated with your surge.sh account. | |
SURGE_TOKEN |
The surge.sh authentication token acquired by logging in and running surge token . |
|
TIMEZONE |
Your timezone in the America/New_York format. It should be available in the TZ database. If not passed in as an environment variable, then the device's current timezone will be assumed to be correct. |
|
TWILIO_ACCOUNT_SID |
The account SID for Twilio which can be acquired on the bottom of the homepage of the Twilio console. Used for Apprise integration of Twilio. | |
TWILIO_AUTH_TOKEN |
The Twilio auth token found on the bottom of the homepage of the Twilio console. Used for Apprise integration of Twilio. | |
TWILIO_FROM_NUMBER |
The number to send out Twilio messages from. Should be registered in your Twilio account and be in the form 13332224444 with the country code included (e.g. 1 for the US in the sample phone number). |
|
TWITTER_ACCESS_TOKEN , TWITTER_ACCESS_TOKEN_SECRET , TWITTER_API_KEY , TWITTER_API_KEY_SECRET |
Various secrets you can generate using the Twitter Developer portal. Integrated into Apprise to allow tweeting from the command-line. Apprise provides details. | |
VAGRANT_CLOUD_TOKEN |
VagrantUp API token stored in ~/.config/shell/private.sh so developer API keys can be loaded by running source "~/.config/shell/private.sh" . |
|
VMWARE_WORKSTATION_LICENSE_KEY |
License key used for pre-registering VMWare Pro or VMWare Fusion | |
VNC_PASSWORD |
VNC password used by macOS VNC system utility or TigerVNC on Linux. Default if not passed in is vncpass . |
|
VNC_READ_PASSWORD |
VNC password used for a read-only session. Default if not passed in is readonly . |
|
WAKATIME_API_KEY |
API key for the Wakatime VSCode time tracking plugin which gets injected into ~/.config/wakatime/.wakatime.cfg |
|
WAZUH_MANAGER |
Address of the Wazuh server to configure the Wazuh client to send data to. Defaults to wazuh.{{ PUBLIC_SERVICES_DOMAIN }} |
|
WINDOWS_11_PRO_KEY |
Activation key for Windows 11 Professional | |
WORK_ENVIRONMENT |
Set to true if you are setting up a corporate device. When true , the provisioning process will avoid installing / configuring things like Tor, which are likely to be banned by corporate networks. This can only be specified as an environment variable. This feature is a WIP. Pull requests welcome. |
*Note: When creating a pull request that introduces new variables, please also open a pull request updating this table to reflect those changes. Include a short description of where and how the variable / secret is used in the description column.
SSH Keys
SSH keys can be saved into your fork by encrypting your files and storing them into the home/.chezmoitemplates/ssh/
folder. During the provisioning process, all of the files in the home/.chezmoitemplates/ssh/
folder are decrypted and placed into your ~/.ssh
folder. For example, if you wanted to encrypt your current id_rsa
file into your fork of Install Doctor, you would run:
chezmoi encrypt "$HOME/id_rsa" > "${XDG_DATA_HOME:-$HOME/.local/share}/chezmoi/home/.chezmoitemplates/ssh/id_rsa"
After that, your id_rsa
file will be encrypted in your fork and you can safely git commit
/ git push
your encrypted id_rsa
file to your public GitHub fork.
VPN Profiles
VPN profiles can be stored in encrypted format into your fork by placing *.ovpn
, *.conf
(WireGuard for macOS), and *.nmconnection
(WireGuard for Linux) files into the home/dot_config/vpn/
folder. Before committing the encrypted configurations into your source, you should encrypt the files with chezmoi encrypt
and then add the following Go template logic to make sure that the files are only decrypted when the decryption key is present:
{{- if (stat (joinPath .host.home ".config" "age" "chezmoi.txt")) -}}
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAraUZ1dkFITlJMbmdhbXUx
ekQ2SjRhaE5uT3J1czh0V09hSkZuanYvUTJvCklTcHZ6RFBrUGx0VlhqQytEb01a
...
-----END AGE ENCRYPTED FILE-----
{{- end -}}
You also have to make sure that the file names are named exactly how you want the profiles to show up in the operating system UI and also:
- Add
private_
to the beginning of the file name so that only your user can read the configurations - Add
.tmpl
to the end of the file name so that the Go template bindings referenced above are handled properly
OVPN Example
The following is an example of the original .ovpn
file that is encrypted and stored in home/dot_config/vpn/
:
client
dev tun
proto tcp
remote 1xx.1xx.1xx.1xx 8443
remote 1xx.1xx.1xx.1xx 7770
remote 1xx.1xx.1xx.1xx 443
remote-random
resolv-retry infinite
nobind
# The following setting is only needed for old OpenVPN clients compatibility. New clients
# automatically negotiate the optimal cipher.
cipher AES-256-CBC
auth SHA512
verb 3
setenv CLIENT_CERT 0
tun-mtu 1500
tun-mtu-extra 32
mssfix 1450
persist-key
persist-tun
reneg-sec 0
remote-cert-tls server
auth-user-pass
pull
fast-io
script-security 2
up /etc/openvpn/update-resolv-conf
down /etc/openvpn/update-resolv-conf
<ca>
-----BEGIN CERTIFICATE-----
MIIFozCCA4ugAwIBAgIBATANBgkqhkiG9w0BAQ0FADBAMxxxxxxxxxxxxxxxxxxx
DK/yPwECUcPgHIeXiRjHnJt0Zcm23O2Q3RphpU+1SO3Xixxxxxxxxxxxxxxxxxxx
A1gTTlpi7A==
-----END CERTIFICATE-----
</ca>
key-direction 1
<tls-auth>
# 2048 bit OpenVPN static key
-----BEGIN OpenVPN Static key V1-----
6acef03f62675b4b1bbd0xxxxxxxxxxx
...
16672ea16c012664f8a9fxxxxxxxxxxx
-----END OpenVPN Static key V1-----
</tls-auth>
After the .ovpn
file is decrypted to ~/.config/vpn/
during the provision process, if the OVPN_PASSWORD
and OVPN_USERNAME
are defined (as either environment variables or secrets stored at home/.chezmoitemplates/secrets/
), then the file will be properly loaded into the NetworkManager on Linux and equivalent programs on macOS / Windows.
It is important to note that we only support passing one set of OVPN_PASSWORD
and OVPN_USERNAME
to the provision process so if you have OpenVPN connections from multiple providers with different usernames and passwords then you will have to extend our default logic.
WireGuard Example
The following is an example of a decrypted .nmconnection
file stored in home/dot_config/vpn/
:
[connection]
id=Proton WG Cambodia (UDP 51820)
uuid=2xxxxxx-30xx-xxxx-xxxx-85xxxxxxxxxx
type=vpn
autoconnect=true
permissions=user:xxx:;
[vpn]
connection-dns=10.2.0.1
local-ip4=10.2.0.2/32
local-private-key=oKHXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX=
peer-allowed-ips=0.0.0.0/0
peer-endpoint=185.159.156.83:51820
peer-public-key=D4M0XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
service-type=org.freedesktop.NetworkManager.wireguard
[ipv4]
dns-search=
method=auto
[ipv6]
addr-gen-mode=stable-privacy
dns-search=
method=auto
[proxy]
As you can see, the authentication keys are located directly in the file so there is no need to load a username and password like in the case of the OpenVPN profiles. The .nmconnection
files are specific to the NetworkManager on Linux systems. You may have to craft the .nmconnection
files by loading your configuration into the NetworkManager program and then grabbing the source from the resulting .nmconnection
file.
On macOS / Windows, the WireGuard .conf
file format is used. The same .nmconnection
file above would look like this in .conf
format:
[Interface]
# NetShield = 1
# Moderate NAT = off
# VPN Accelerator = on
PrivateKey = oKHXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX=
Address = 10.2.0.2/32
DNS = 10.2.0.1
[Peer]
# SE-KH#1
PublicKey = D4M0XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
AllowedIPs = 0.0.0.0/0
Endpoint = 185.159.156.83:51820
Encrypted Files
There are a few cases where entire files need to be encrypted. Whenever possible, in cases like Tabby's configuration stored at home/dot_config/tabby/config.yaml.tmpl
the optimized configuration stripped of secrets is provided as a fallback within the template. In cases like this, where no environment variable configuration parameter is made available, the encrypted file parts are stored in home/.chezmoitemplates/files/
. The table below describes the capabilities that are offered by these files:
File in .chezmoitemplates/files/ |
Description |
---|---|
tabby |
The Tabby configuration file which can include several types of encryption keys in it. Used in home/dot_config/tabby/config.yaml.tmpl . |
google-assistant-client-secret |
The client secret required for the unofficial Google Assistant desktop applications. Details on how to set it can be found on the project's wiki. Used in home/dot_config/Google Assistant/client-secret.json.tmpl . The google-assistant-tokens file is also required (details below). |
google-assistant-tokens |
The tokens required for setting up the unofficial Google Assistant. Used in home/dot_config/Google Assistant/tokens.json.tmpl . The google-assistant-client-secret is also required (details above) |
gphotos-sync |
The Google Photos API client secret file required for using gphotos-sync to backup your Google Photos content. Used in home/dot_config/gphotos-sync/client_secret.json.tmpl . |
If you inspect the files above, you will see that they are stored in their target location as a template that first checks if the encryption key is present. If the key is present, the files get decrypted. Ideally, if the key is not present, then a version of the file without sensitive information should be rendered. An example of this can be found in the Tabby configuration (home/dot_config/tabby/config.yaml
). When contributing to this project, be sure to include this fallback logic whenever possible so that users who have not populated their fork with encrypted secrets can still retain functionality.
Creating New Variables / Secrets
If you want to expand the capabilities of your fork beyond what we have provided, we recommend you follow the same approach we use when handling environment variables and secret encrypted keys.
Combining Variables and Secrets
Ideally, whenever possible, the user should be able to pass in a variable as either an environment variable or as a secret included in the fork. In the ~/.config/shell/private.sh
file which houses private keys for cloud APIs that the user may want to source by running . "~/.config/shell/private.sh"
, the DockerHub token is defined with:
export DOCKERHUB_TOKEN="{{ if (stat (joinPath .chezmoi.sourceDir ".chezmoitemplates" "secrets" "key-DOCKERHUB_TOKEN")) }}{{ includeTemplate "secrets/key-DOCKERHUB_TOKEN" }}{{ else }}{{ env "DOCKERHUB_TOKEN" }}{{ end }}"
export DOCKERHUB_REGISTRY_PASSWORD="$DOCKERHUB_TOKEN"
This approach works well because it first checks for the presence of the home/.chezmoitemplates/secrets/key-DOCKERHUB_TOKEN
file and then decrypts the value and injects it into the results private.sh
file if the key-DOCKERHUB_TOKEN
is present. Otherwise, it attempts to use the DOCKERHUB_TOKEN
key.
Note: Preferrably, you should store the secret as the same name as the corresponding environment variable. That is, an environment variable named DOCKERHUB_TOKEN
should be stored as a key stored in home/.chezmoitemplates/secrets/key-DOCKERHUB_TOKEN
. Additionally, encrypted files that decrypt to files stored in ~/.ssh/
should be prefixed with ssh-
instead of key-
.
Encrypted Files
For encrypted files, you should mark the file as a templated file by ending the file name with .tmpl
and then you should include a check to make sure both the decryption key and the encrypted secret data location is available. For example, our ~/.ssh/id_rsa
file is generated by placing a file in home/private_dot_ssh/private_id_rsa.tmpl
with the following content that makes these checks:
{{- if and (stat (joinPath .host.home ".config" "age" "chezmoi.txt")) (stat (joinPath .chezmoi.sourceDir ".chezmoitemplates" "secrets" "ssh-id-rsa")) -}}
{{ includeTemplate "secrets/ssh-id-rsa" | decrypt -}}
{{ end -}}
At provisioning time, if the necessary files are available, the encrypted secret data stored in home/.chezmoitemplates/secrets/ssh-id-rsa
will be decrypted and added to the ~/.ssh/id_rsa
file.