move certs to ./.lego directory

This commit is contained in:
m5r 2024-07-20 02:43:52 +02:00
parent 43788570ee
commit b97b2f2131
Signed by: mokhtar
GPG Key ID: 1509B54946D08A95
5 changed files with 34 additions and 32 deletions

View File

@ -8,15 +8,20 @@ RUN CGO_ENABLED=0 go build -o /app/local-ip
FROM gcr.io/distroless/base-debian12:latest
ENV PORT 53
WORKDIR /local-ip
WORKDIR /app
COPY --from=build /app/local-ip /local-ip/local-ip
COPY --from=build /app/http/static /local-ip/http/static
COPY --from=build /app/local-ip /app/local-ip
COPY --from=build /app/http/static /app/http/static
COPY ./.lego /app/.lego
VOLUME /local-ip/.lego
# DNS
EXPOSE 53/udp
# HTTP
EXPOSE 80/tcp
# HTTPS
EXPOSE 443/tcp
EXPOSE $PORT
USER root
CMD ["/app/local-ip"]
CMD ["/local-ip/local-ip"]

View File

@ -1,6 +1,6 @@
# local-ip.sh
[local-ip.sh](https://local-ip.sh) is a magic domain name that provides wildcard DNS for any IP address.
[local-ip.sh](https://local-ip.sh) is a magic domain name that provides wildcard DNS for any IP address.
It is heavily inspired by [local-ip.co](http://local-ip.co), [sslip.io](https://sslip.io), and [xip.io](https://xip.io)
## Usage
@ -22,16 +22,13 @@ dig @localhost 127.0.0.1.my.local-ip.sh +short
local-ip.sh packs up:
- an authoritative DNS server that answers queries for the zone `local-ip.sh`
- a Let's Encrypt client that takes care of obtaining and renewing the wildcard certificate for `*.local-ip.sh` using the DNS-01 challenge
- an HTTP server that serves the certificate files
- a Let's Encrypt client that takes care of obtaining and renewing the wildcard certificate for `*.local-ip.sh` and the root certificate for `local-ip.sh` using the [DNS-01 challenge](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge)
- an HTTP server that serves static files, including the certificate files
It answers queries with the IPv4 address it may find in the subdomain by pattern matching the FQDN.
It answers queries with the IPv4 address it may find in the subdomain by pattern matching the FQDN.
It registers an account to Let's Encrypt's ACME server to obtain the wildcard certificate on the first run and then renew
it about a month before it expires. The account file and the associated key used to request a certificate under the `.lego`
directory but the certificate's files are stored in `/certs` at the root of the filesystem. I've done it this way to mount
a persistent storage volume there and keep the files between deployments without tracking them in git but feel free to
change this behavior in [`certs/certs.go`](./certs/certs.go) and in [`http/server.go`](./http/server.go)
if you're planning to self-host it.
it about a month before it expires. The account file and the associated key used to request a certificate under the `./.lego/accounts`
directory and the certificate's files are stored in `./.lego/certs`.
The certificate files are served by an HTTP server on the arbitrary port `:9229` that is intentionally not exposed to
the internet. [The website](https://local-ip.sh) is connected to the same private network as the service and serves

View File

@ -92,19 +92,19 @@ func (c *certsClient) renewCertificates() {
}
func persistFiles(certificates *certificate.Resource, certType string) {
err := os.MkdirAll(fmt.Sprintf("/certs/%s", certType), 0o755)
err := os.MkdirAll(fmt.Sprintf("./.lego/certs/%s", certType), 0o755)
if err != nil {
utils.Logger.Fatal().Err(err).Msgf("Failed to mkdir /certs/%s", certType)
utils.Logger.Fatal().Err(err).Msgf("Failed to mkdir ./.lego/certs/%s", certType)
}
err = os.WriteFile(fmt.Sprintf("/certs/%s/server.pem", certType), certificates.Certificate, 0o644)
err = os.WriteFile(fmt.Sprintf("./.lego/certs/%s/server.pem", certType), certificates.Certificate, 0o644)
if err != nil {
utils.Logger.Fatal().Err(err).Msgf("Failed to save /certs/%s/server.pem", certType)
utils.Logger.Fatal().Err(err).Msgf("Failed to save ./.lego/certs/%s/server.pem", certType)
}
os.WriteFile(fmt.Sprintf("/certs/%s/server.key", certType), certificates.PrivateKey, 0o644)
os.WriteFile(fmt.Sprintf("./.lego/certs/%s/server.key", certType), certificates.PrivateKey, 0o644)
if err != nil {
utils.Logger.Fatal().Err(err).Msgf("Failed to save /certs/%s/server.key", certType)
utils.Logger.Fatal().Err(err).Msgf("Failed to save ./.lego/certs/%s/server.key", certType)
}
jsonBytes, err := json.MarshalIndent(certificates, "", "\t")
@ -112,9 +112,9 @@ func persistFiles(certificates *certificate.Resource, certType string) {
utils.Logger.Fatal().Err(err).Msg("Failed to marshal certificates to JSON")
}
err = os.WriteFile(fmt.Sprintf("/certs/%s/output.json", certType), jsonBytes, 0o644)
err = os.WriteFile(fmt.Sprintf("./.lego/certs/%s/output.json", certType), jsonBytes, 0o644)
if err != nil {
utils.Logger.Fatal().Err(err).Msgf("Failed to save /certs/%s/output.json", certType)
utils.Logger.Fatal().Err(err).Msgf("Failed to save ./.lego/certs/%s/output.json", certType)
}
}
@ -140,7 +140,7 @@ func NewCertsClient(xip *xip.Xip, user *Account) *certsClient {
}
func getLastCertificate(legoClient *lego.Client, certType string) *certificate.Resource {
jsonBytes, err := os.ReadFile(fmt.Sprintf("/certs/%s/output.json", certType))
jsonBytes, err := os.ReadFile(fmt.Sprintf("./.lego/certs/%s/output.json", certType))
if err != nil {
if strings.Contains(err.Error(), "no such file or directory") {
return nil

View File

@ -17,8 +17,8 @@ auto_rollback = true
PORT = "53"
[mounts]
source = "certs"
destination = "/certs"
source = "lego"
destination = "/local-ip/.lego"
[[services]]
protocol = "udp"

View File

@ -13,11 +13,11 @@ import (
func registerHandlers() {
http.HandleFunc("GET /server.key", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/octet-stream")
http.ServeFile(w, r, "/certs/wildcard/server.key")
http.ServeFile(w, r, "./.lego/certs/wildcard/server.key")
})
http.HandleFunc("GET /server.pem", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/x-x509-ca-cert")
http.ServeFile(w, r, "/certs/wildcard/server.pem")
http.ServeFile(w, r, "./.lego/certs/wildcard/server.pem")
})
http.HandleFunc("GET /og.png", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "image/png; charset=utf-8")
@ -58,13 +58,13 @@ func serveHttp() *http.Server {
func waitForCertificate(ready chan bool) {
for {
_, err := os.Stat("/certs/root/output.json")
_, err := os.Stat("./.lego/certs/root/output.json")
if err != nil {
if strings.Contains(err.Error(), "no such file or directory") {
time.Sleep(1 * time.Second)
continue
}
utils.Logger.Fatal().Err(err).Msg("Unexpected error while looking for /certs/root/output.json")
utils.Logger.Fatal().Err(err).Msg("Unexpected error while looking for ./.lego/certs/root/output.json")
}
break
}
@ -100,7 +100,7 @@ func redirectHttpToHttps() {
func serveHttps() {
utils.Logger.Info().Msg("Starting up HTTPS server on :443")
httpsServer := &http.Server{Addr: ":https"}
go httpsServer.ListenAndServeTLS("/certs/root/server.pem", "/certs/root/server.key")
go httpsServer.ListenAndServeTLS("./.lego/certs/root/server.pem", "./.lego/certs/root/server.key")
}
func ServeHttp() {