new version

This commit is contained in:
mi6e4ka 2024-10-30 22:11:04 +03:00
parent 53a1aa2cc5
commit b33bed8745
8 changed files with 127 additions and 126 deletions

View File

@ -1 +1,2 @@
.env .env
certs

3
.gitignore vendored
View File

@ -1 +1,2 @@
.env .env
certs

View File

@ -1,16 +1,16 @@
FROM golang:1.22-alpine as build FROM docker.io/golang:1.22-alpine as build
WORKDIR /app WORKDIR /app
COPY . . COPY . .
ENV GOCACHE=/root/.cache/go-build ENV GOCACHE=/root/.cache/go-build
RUN --mount=type=cache,target="/root/.cache/go-build" go build . RUN --mount=type=cache,target="/root/.cache/go-build" go build -ldflags="-w -s" -gcflags=all=-l .
RUN --mount=type=cache,target="/root/.cache/go-build" go build -C cert .
FROM nginx:alpine-slim FROM scratch
COPY --from=build app app COPY --from=build app app
# copy ssl for work HTTPS requests to gitea instance
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
WORKDIR /app WORKDIR /app
COPY nginx.conf /etc/nginx/nginx.conf ENV GIN_MODE=release
ENTRYPOINT [ "./giteapages" ]
ENTRYPOINT [ "sh", "entrypoint.sh" ]

View File

@ -1,5 +1,38 @@
## currently hosted by me on
https://pages.mi6e4ka.dev
# how to run # how to run
`docker run -p 443:443 -p 80:80 --name gitea-pages -v gitea-pages-ssl:/etc/ssl -d gitea-pages`
## gen ssl (first run) `docker run -p 8080:8080 --name gitea-pages -d git.mi6e4ka.dev/mi6e4ka/gitea-pages`
`docker exec -it gp /app/cert/cert root.domain` ```
and restart docker container! issue wildcard ssl for domains *.rootdomain and rootdomain should be your reverse proxy
```
or by docker-compose
```
services:
gitea-pages:
env_file: ".env"
image: git.mi6e4ka.dev/mi6e4ka/gitea-pages
ports:
- 8080:8080
```
## ENV SETTINGS
also by create .env file
<!--
PDNS_KEY | | RvvA8qH8kkH3 | yes | PowerDNS api key
PDNS_HOST | | http://10.0.0.4:8081 | yes | PowerDNS api host
ACME_EMAIL | | me@example.com | yes | ACME email
TEST_MODE | false | true | Issue stagins le certs
-->
param | default | eg | description
--- | --- | ---| ---
ROOT_DOMAIN | localhost | my.pages | root domain to serve sites
DEFAULT_USER | | mi6e4ka | Gitea user if not specified user subdomain
GITEA_URL | https://codeberg.org | | Gitea instance with api
INDEX_FILE | index.html | | File serving by default
DIRECTORY_INDEX | false | true | Show list files if not index.html in directory
SERVE_PORT | 8080 | | Port to listen
GITEA_TOKEN | | 5yE5j5r1qHZI | For access to private repos

View File

@ -7,12 +7,14 @@ import (
"crypto/rand" "crypto/rand"
"fmt" "fmt"
"log" "log"
"net/url"
"os" "os"
"time"
"github.com/go-acme/lego/v4/certcrypto" "github.com/go-acme/lego/v4/certcrypto"
"github.com/go-acme/lego/v4/certificate" "github.com/go-acme/lego/v4/certificate"
"github.com/go-acme/lego/v4/challenge/dns01"
"github.com/go-acme/lego/v4/lego" "github.com/go-acme/lego/v4/lego"
"github.com/go-acme/lego/v4/providers/dns/pdns"
"github.com/go-acme/lego/v4/registration" "github.com/go-acme/lego/v4/registration"
) )
@ -33,60 +35,62 @@ func (u *MyUser) GetPrivateKey() crypto.PrivateKey {
return u.key return u.key
} }
type DNSProviderBestDNS struct { func GenCerts() {
apiAuthToken string testMode := false
} testModeStr, exists := os.LookupEnv("TEST_MODE")
if !exists {
func NewDNSProviderBestDNS(apiAuthToken string) (*DNSProviderBestDNS, error) { if testModeStr == "true" {
return &DNSProviderBestDNS{apiAuthToken: apiAuthToken}, nil testMode = true
} }
func (d *DNSProviderBestDNS) Present(domain, token, keyAuth string) error { }
info := dns01.GetChallengeInfo(domain, keyAuth) rootDomain, exists := os.LookupEnv("ROOT_DOMAIN")
fmt.Println() if !exists {
fmt.Println("------") rootDomain = "localhost"
fmt.Println() }
fmt.Println("Please create DNS TXT record, for domain", info.FQDN, "with these content:") pdnsKey, has := os.LookupEnv("PDNS_KEY")
fmt.Println() if !has {
fmt.Println(info.Value) fmt.Println("must have PDNS_KEY")
fmt.Println()
fmt.Println("------")
fmt.Scanln()
// make API request to set a TXT record on fqdn with value and TTL
return nil
}
func (d *DNSProviderBestDNS) CleanUp(domain, token, keyAuth string) error {
// clean up any state you created in Present, like removing the TXT record
fmt.Println("------")
fmt.Println()
fmt.Println("you can delete the TXT record, and press enter to continue")
fmt.Println()
fmt.Println("------")
fmt.Scanln()
return nil
}
func main() {
if len(os.Args) != 2 {
fmt.Println("usage: ./cert root.domain")
os.Exit(1) os.Exit(1)
} }
fmt.Println("root domain is", os.Args[1]) pdnsHost, has := os.LookupEnv("PDNS_HOST")
if !has {
fmt.Println("must have PDNS_HOST ENV")
os.Exit(1)
}
acmeEmail, has := os.LookupEnv("ACME_EMAIL")
if !has {
fmt.Println("must have ACME_EMAIL ENV")
os.Exit(1)
}
fmt.Println("root domain is", rootDomain)
// Create a user. New accounts need an email and private key to start. // Create a user. New accounts need an email and private key to start.
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
var email string
fmt.Print("enter you email > ")
fmt.Scanln(&email)
myUser := MyUser{ myUser := MyUser{
Email: email, Email: acmeEmail,
key: privateKey, key: privateKey,
} }
pdnsUrl, _ := url.Parse(pdnsHost)
provider, err := pdns.NewDNSProviderConfig(&pdns.Config{
Host: pdnsUrl,
APIKey: pdnsKey,
ServerName: "localhost",
TTL: 5,
PropagationTimeout: time.Duration(time.Second * 30),
PollingInterval: time.Duration(time.Millisecond * 500),
})
if err != nil {
log.Fatal(err)
}
config := lego.NewConfig(&myUser) config := lego.NewConfig(&myUser)
// uncoment for tesing ->>
if testMode {
config.CADirURL = lego.LEDirectoryStaging
}
//config.CADirURL = lego.LEDirectoryStaging
config.Certificate.KeyType = certcrypto.RSA2048 config.Certificate.KeyType = certcrypto.RSA2048
// A client facilitates communication with the CA server. // A client facilitates communication with the CA server.
@ -94,15 +98,7 @@ func main() {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
client.Challenge.SetDNS01Provider(provider)
bestDNS, err := NewDNSProviderBestDNS("my-auth-token")
if err != nil {
log.Fatal(err)
}
err = client.Challenge.SetDNS01Provider(bestDNS)
if err != nil {
log.Fatal(err)
}
// New users will need to register // New users will need to register
reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true}) reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
@ -112,7 +108,7 @@ func main() {
myUser.Registration = reg myUser.Registration = reg
request := certificate.ObtainRequest{ request := certificate.ObtainRequest{
Domains: []string{os.Args[1], "*." + os.Args[1]}, Domains: []string{rootDomain, "*." + rootDomain},
Bundle: true, Bundle: true,
} }
certificates, err := client.Certificate.Obtain(request) certificates, err := client.Certificate.Obtain(request)
@ -122,9 +118,9 @@ func main() {
// Each certificate comes back with the cert bytes, the bytes of the client's // Each certificate comes back with the cert bytes, the bytes of the client's
// private key, and a certificate URL. SAVE THESE TO DISK. // private key, and a certificate URL. SAVE THESE TO DISK.
os.Mkdir("/etc/ssl", 0777) os.Mkdir("./certs", 0777)
os.WriteFile("/etc/ssl/cert.crt", certificates.Certificate, 0777) os.WriteFile("./certs/cert.crt", certificates.Certificate, 0777)
os.WriteFile("/etc/ssl/priv.key", certificates.PrivateKey, 0777) os.WriteFile("./certs/priv.key", certificates.PrivateKey, 0777)
// ... all done. // ... all done.
} }

View File

@ -1,8 +0,0 @@
#!/bin/bash
if [ -e /etc/ssl/cert.crt ] && [ -e /etc/ssl/priv.key ]
then
nginx & GIN_MODE=release ./giteapages
else
echo "create certs first"
tail -f /dev/null
fi

31
main.go
View File

@ -3,6 +3,7 @@ package main
import ( import (
"embed" "embed"
"encoding/json" "encoding/json"
"fmt"
"html/template" "html/template"
"io" "io"
"mime" "mime"
@ -32,6 +33,29 @@ func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) {
func main() { func main() {
godotenv.Load() godotenv.Load()
// if os.Args[len(os.Args)-1] == "gencrt" {
// GenCerts()
// os.Exit(0)
// }
// if _, err := os.Stat("./certs/cert.crt"); err != nil {
// fmt.Println("Not found cert file")
// GenCerts()
// }
// if _, err := os.Stat("./certs/priv.key"); err != nil {
// fmt.Println("Not fount cert key file")
// GenCerts()
// }
//certFile, _ := os.ReadFile("./certs/cert.crt")
//block, _ := pem.Decode(certFile)
//if block == nil {
// fmt.Println("invalid certificate")
// GenCerts()
// }
// cert, _ := x509.ParseCertificate(block.Bytes)
// certExpired := time.Now().After(cert.NotAfter)
// if certExpired {
// GenCerts()
// }
rootDomain, exists := os.LookupEnv("ROOT_DOMAIN") rootDomain, exists := os.LookupEnv("ROOT_DOMAIN")
if !exists { if !exists {
rootDomain = "localhost" rootDomain = "localhost"
@ -49,9 +73,10 @@ func main() {
indexFile = "index.html" indexFile = "index.html"
} }
directoryIndexStr := os.Getenv("DIRECTORY_INDEX") directoryIndexStr := os.Getenv("DIRECTORY_INDEX")
directoryIndex := true fmt.Println(rootDomain, giteaUrl)
if directoryIndexStr == "false" { directoryIndex := false
directoryIndex = false if directoryIndexStr == "true" {
directoryIndex = true
} }
defaultUser := os.Getenv("DEFAULT_USER") defaultUser := os.Getenv("DEFAULT_USER")
servePort, exists := os.LookupEnv("SERVE_PORT") servePort, exists := os.LookupEnv("SERVE_PORT")

View File

@ -1,47 +0,0 @@
worker_processes 1;
events { worker_connections 1024; }
http {
sendfile on;
large_client_header_buffers 4 32k;
upstream web-api {
server localhost:8080;
}
server {
listen 80 default_server;
server_name _;
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name _;
ssl_certificate /etc/ssl/cert.crt;
ssl_certificate_key /etc/ssl/priv.key;
location / {
proxy_pass http://web-api;
proxy_redirect off;
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $server_name;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
}
}
}