Skip to content

Commit

Permalink
fix: install root certs correctly by changing how daemonization works (
Browse files Browse the repository at this point in the history
…#31)

## Bugfix

Fix #30 by changing how daemonization works. 

- Previously: `start`/`reload` would apply the latest config in the
foreground process, then fork(), then start Caddy.
- Now: `start`/`reload` apply the latest config, starts Caddy in the
foreground process, then fork()s.
- By starting Caddy in the foreground process, any activities requiring
sudo/root will happen while the program is still interactive.
- This fixes the problem (adding the root cert to the system store
requires sudo/root privileges, but because Caddy was running in a
background process, it couldn't request that permission.)
- The foreground process exits cleanly and the background process starts
Caddy again, this time without any need for sudo/root privileges because
any of the work it needed to do was already done in the foreground
process.

## Friendlier CLI

This change encouraged me to make the following improvements to the CLI
commands:

- `stop` just kills the daemon, if it's running. If the daemon wasn't
running, `stop` will now exit cleanly. Previously, it would throw an
error, but that's user-hostile because the goal of running `stop` is to
ensure no running daemon — if that goal is accomplished by stopping a
running daemon, or confirming no daemon was running, doesn't really
matter.
- `start` will start a new daemon. If one was already running, it will
be killed and replaced by a new one. The user's goal is to ensure a
daemon is running, with the latest config, and this is achieved
regardless of whether or not there was an existing daemon.
- `reload` becomes an alias for `start`, because they have the exact
same behavior — ensure that a daemon is running with the latest
configuiration.

## Get rid of `caddymodules`

A while ago, localias was built using `gomod2nix`, and there was an
incompatibility between that helper and the opentelemetry modules
included in Caddy. To work around this, I created a `caddymodules`
package that imported all of the Caddy modules _except_ opentelemetry,
which was fine because this project doesn't use the opentelemetry
modules in any way.

Because localias no longer uses `gomod2nix`, this PR gets rid of the
`caddymodules` hack entirely. This then allowed me to upgrade the
version of Caddy that is being installed, and it will make it easier to
stay up to date as Caddy receives further improvements.

## SSL renewal server

With an upgraded Caddy came a problem — for SSL issuance, Caddy now
requires you to implement an "automation policy" server that confirms
that it can issue a new certificate for a given domain. This is
primarily aimed at issuing certificates for real life domains accessible
to the public, not for internal development aliases, but the restriction
still stands. To do this, I used Caddy itself to respond to these
requests.

For more information, read:
- https://caddyserver.com/docs/automatic-https#on-demand-tls
-
https://caddy.community/t/serving-tens-of-thousands-of-domains-over-https-with-caddy/11179
- caddyserver/caddy#6055

In the future, I could implement this by writing a custom policy module
instead of using the HTTP ask, but this works for now.

## Dependencies cleanup

- General updates of all imported golang packages.
- Update the `flake.nix` and `flake.lock` files, switch to
`buildGoModule` instead of `buildGo120Module` to make it easier to use
this flake with an override `nixpkgs` upstream.
  • Loading branch information
peterldowns authored May 12, 2024
1 parent fe5d709 commit 46b0a47
Show file tree
Hide file tree
Showing 38 changed files with 810 additions and 723 deletions.
21 changes: 15 additions & 6 deletions .github/workflows/golang.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: setup-go
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: '1.20'
go-version: '1.22'
cache: true
cache-dependency-path: go.sum
- name: build
Expand All @@ -24,12 +24,21 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: setup-go
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: '1.20'
go-version: '1.22'
cache: true
cache-dependency-path: go.sum
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
uses: golangci/golangci-lint-action@v5
with:
version: v1.55.2
install-mode: "binary"
version: "v1.58.0"
# https://github.com/golangci/golangci-lint-action/issues/244
# https://github.com/Kong/mesh-perf/pull/168
skip-cache: true
- name: go mod tidy
run: go mod tidy
- name: check for any changes
run: |
[[ $(git status --porcelain) == "" ]] || (echo "changes detected" && exit 1)
33 changes: 8 additions & 25 deletions .github/workflows/nix.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,32 +16,15 @@ jobs:
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
- name: Install Cache
uses: DeterminateSystems/magic-nix-cache-action@v1
# flakes
- run: nix develop --command which go
- run: nix build . && ./result/bin/localias --help
- run: nix build .#localias && ./result/bin/localias --help
- run: nix run . -- --help
- run: nix run .#localias -- --help
uses: DeterminateSystems/magic-nix-cache-action@v4
- run: nix flake check
# standard
- run: nix-shell --run 'which go'
- run: nix-build && ./result/bin/localias --help
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Nix
uses: cachix/install-nix-action@v22
with:
nix_path: nixpkgs=channel:nixos-unstable
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
- name: Install Cache
uses: DeterminateSystems/magic-nix-cache-action@v1
- run: find . -name '*.nix' | xargs nix run nixpkgs#nixpkgs-fmt --
- run: |
# confirms that the shell works, and that there are no linting errors
- name: lint formatting
run: |
nix develop --command bash -c "find . -name '*.nix' | xargs nixpkgs-fmt"
if ! git diff-index --quiet HEAD --; then
echo "gomod2nix had changes"
echo "nixpkgs-fmt had changes"
exit 1
fi
# confirms that the build works
- run: nix build .
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- name: setup-go
uses: actions/setup-go@v4
with:
go-version: '1.20'
go-version: '1.22'
cache: true
cache-dependency-path: go.sum
- name: release-darwin-amd64
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# created by the vscode debugger
__debug_bin
**/__debug_bin*

# we use this to store the golang modules and caches
.toolchain/
Expand Down
77 changes: 52 additions & 25 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# yaml-language-server: $schema=https://json.schemastore.org/golangci-lint.json
# https://golangci-lint.run/usage/configuration/
linters-settings:
gocritic:
disabled-checks:
- ifElseChain
goimports:
local-prefixes: github.com/peterldowns/localias
local-prefixes: github.com/peterldowns/panoctocon
govet:
enable-all: true
disable:
Expand All @@ -12,96 +14,121 @@ linters-settings:
default-signifies-exhaustive: true
nolintlint:
allow-unused: false
allow-leading-space: false
allow-no-explanation: [depguard, gochecknoglobals, gochecknoinits]
allow-no-explanation:
- gochecknoglobals
- gochecknoinits
- unparam
require-explanation: true
require-specific: true
# golint is deprecated. The recommended replacement is revive, which is a drop-in replacement
# for golint with additional rules and configuration options. For a list of available rules and
# configurations, see https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md.
# Rules below that are commented out require some minor refactoring before they can be enabled.
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md
revive:
enable-all-rules: false
rules:
- name: atomic
- name: blank-imports
#- name: blank-imports
- name: bare-return
- name: bool-literal-in-expr
- name: call-to-gc
# - name: confusing-results
- name: comment-spacings
arguments: ["nolint"]
- name: confusing-results
- name: constant-logical-expr
- name: context-as-argument
arguments:
- allowTypesBefore: "*testing.T"
- name: context-keys-type
# - name: deep-exit
# - name: defer
# arguments: [[call-chain, loop, method-call, recover]]
- name: datarace
- name: deep-exit
- name: defer
- name: dot-imports
- name: duplicated-imports
# - name: early-return
- name: early-return
- name: empty-block
- name: empty-lines
- name: error-naming
- name: error-return
- name: error-strings
- name: errorf
- name: exported
# - name: flag-parameter
# - name: get-return
- name: function-result-limit
arguments: [3]
- name: get-return
- name: identical-branches
# - name: if-return
# - name: import-shadowing
- name: if-return
- name: imports-blacklist
arguments: []
- name: import-shadowing
- name: increment-decrement
- name: indent-error-flow
- name: modifies-parameter
- name: modifies-value-receiver
- name: nested-structs
- name: package-comments
- name: range
- name: range-val-address
- name: range-val-in-closure
- name: receiver-naming
- name: redefines-builtin-id
- name: string-format
- name: string-of-int
- name: struct-tag
# - name: superfluous-else
- name: superfluous-else
- name: time-equal
- name: time-naming
- name: unconditional-recursion
- name: unexported-naming
- name: unexported-return
- name: unhandled-error
arguments:
- "fmt.*"
- "strings.Builder.WriteString"
- name: unnecessary-stmt
- name: unreachable-code
- name: unused-parameter
# - name: unused-receiver
- name: unused-receiver
- name: use-any
- name: useless-break
- name: var-declaration
- name: var-naming
- name: waitgroup-by-value
run:
tests: true
timeout: 1m
args:
- "--skip-dirs-use-default"
- "."
dirs:
- "."

# https://golangci-lint.run/usage/linters/
linters:
disable-all: true
enable:
- asciicheck
- errcheck
- errorlint
- exhaustive
- gochecknoglobals
- gochecknoinits
- gocritic
- gofmt
- gofumpt
- goimports
- gosimple
- gomodguard
- govet
- ineffassign
- nolintlint
- revive
- staticcheck
- typecheck
- unparam
- unused
- whitespace
- paralleltest
- errname
- errorlint
- gosimple
- unparam
issues:
exclude:
# Allow shadowing of `err` because it's so common
- 'declaration of "err" shadows declaration at'
max-same-issues: 10000
max-issues-per-linter: 10000
exclude-dirs:
- pkg/database/models
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"type": "go",
"request": "launch",
"mode": "debug",
"args": ["daemon", "status"],
"args": ["run"],
"program": "./cmd/localias",

}
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.0.3
2.1.0
2 changes: 1 addition & 1 deletion cmd/localias/debug/cert.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ var certCmd = &cobra.Command{ //nolint:gochecknoglobals
RunE: certImpl,
}

func init() { //nolint:gochecknoinits
func init() {
certFlags.Print = certCmd.Flags().BoolP("print", "p", false, "print the contents of the certificate")
certFlags.Install = certCmd.Flags().BoolP("install", "i", false, "install the certificate to the windows cert store")
Command.AddCommand(certCmd)
Expand Down
2 changes: 1 addition & 1 deletion cmd/localias/debug/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ var configCmd = &cobra.Command{ //nolint:gochecknoglobals
RunE: configImpl,
}

func init() { //nolint:gochecknoinits
func init() {
configFlags.Print = configCmd.Flags().BoolP("print", "p", false, "print the contents of the config file")
Command.AddCommand(configCmd)
}
2 changes: 1 addition & 1 deletion cmd/localias/debug/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ localias debug cert --print
Hidden: true,
}

func init() { //nolint:gochecknoinits
func init() {
Command.AddCommand(hostctl.Command)
}
7 changes: 2 additions & 5 deletions cmd/localias/debug/hostctl/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@ import (
func applyImpl(_ *cobra.Command, _ []string) error {
cfg := shared.Config()
hctl := shared.Controller()
if err := config.Apply(hctl, cfg); err != nil {
return err
}
return nil
return config.Apply(hctl, cfg)
}

var applyCmd = &cobra.Command{ //nolint:gochecknoglobals
Expand All @@ -23,6 +20,6 @@ var applyCmd = &cobra.Command{ //nolint:gochecknoglobals
RunE: applyImpl,
}

func init() { //nolint:gochecknoinits
func init() {
Command.AddCommand(applyCmd)
}
2 changes: 1 addition & 1 deletion cmd/localias/debug/hostctl/clear.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ var clearCmd = &cobra.Command{ //nolint:gochecknoglobals
RunE: clearImpl,
}

func init() { //nolint:gochecknoinits
func init() {
Command.AddCommand(clearCmd)
}
2 changes: 1 addition & 1 deletion cmd/localias/debug/hostctl/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ var listCmd = &cobra.Command{ //nolint:gochecknoglobals
RunE: listImpl,
}

func init() { //nolint:gochecknoinits
func init() {
Command.AddCommand(listCmd)
}
2 changes: 1 addition & 1 deletion cmd/localias/debug/hostctl/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ var pathCmd = &cobra.Command{ //nolint:gochecknoglobals
RunE: pathImpl,
}

func init() { //nolint:gochecknoinits
func init() {
Command.AddCommand(pathCmd)
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/localias/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@ func onError(err error) {
err = shared.ConvertErr(err)
msg := fmt.Sprintf("error: %s", err)
fmt.Fprintln(os.Stderr, color.New(color.FgRed, color.Italic).Sprintf(msg))
os.Exit(1)
os.Exit(1) //nolint:revive // intentional
}
2 changes: 1 addition & 1 deletion cmd/localias/root/clear.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ func clearImpl(_ *cobra.Command, _ []string) error {
return nil
}

func init() { //nolint:gochecknoinits
func init() {
Command.AddCommand(clearCmd)
}
2 changes: 1 addition & 1 deletion cmd/localias/root/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ func listImpl(_ *cobra.Command, _ []string) error {
return nil
}

func init() { //nolint:gochecknoinits
func init() {
Command.AddCommand(listCmd)
}
39 changes: 0 additions & 39 deletions cmd/localias/root/reload.go

This file was deleted.

Loading

0 comments on commit 46b0a47

Please sign in to comment.