aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/appsluggr/main.go165
-rw-r--r--cmd/dnsd/Dockerfile11
-rw-r--r--cmd/dnsd/README.md88
-rw-r--r--cmd/dnsd/dnsd.conf7
-rw-r--r--cmd/dnsd/dnsd.service12
-rw-r--r--cmd/dnsd/main.go169
-rw-r--r--cmd/genua/main.go20
-rw-r--r--cmd/minipaas/main.go21
-rw-r--r--cmd/thumber/in/XjScp8a.pngbin292689 -> 0 bytes
-rw-r--r--cmd/thumber/in/lB4ICS3.pngbin369886 -> 0 bytes
-rw-r--r--cmd/thumber/in/oaw79y9.jpgbin67119 -> 0 bytes
-rw-r--r--cmd/thumber/main.go58
-rw-r--r--cmd/tlstestd/main.go31
-rw-r--r--cmd/tor2web/main.go58
-rw-r--r--cmd/within.website/build.go58
-rw-r--r--cmd/xedn/build.go10
-rw-r--r--docs/man1/appsluggr.1113
-rw-r--r--internal/appsluggr/appsluggr.go112
-rw-r--r--tor/tor.go88
19 files changed, 118 insertions, 903 deletions
diff --git a/cmd/appsluggr/main.go b/cmd/appsluggr/main.go
deleted file mode 100644
index 9a90796..0000000
--- a/cmd/appsluggr/main.go
+++ /dev/null
@@ -1,165 +0,0 @@
-// Command appsluggr packages a standard web and worker slug for Heroku/Dokku.
-//
-// This hard assumes that the binaries put into the slug will work on the target hardware.
-package main
-
-import (
- "archive/tar"
- "compress/gzip"
- "flag"
- "fmt"
- "io"
- "io/ioutil"
- "log"
- "os"
- "path/filepath"
- "strings"
-
- "github.com/otiai10/copy"
- "golang.org/x/mod/sumdb/dirhash"
- "within.website/x/internal"
-)
-
-var (
- web = flag.String("web", "", "path to binary for web process")
- webScale = flag.Int("web-scale", 1, "default scale for web process if defined")
- worker = flag.String("worker", "", "path to binary for worker process")
- workerScale = flag.Int("worker-scale", 1, "default scale for worker process if defined")
- fname = flag.String("fname", "slug.tar.gz", "slug name")
-)
-
-func main() {
- internal.HandleStartup()
-
- fout, err := os.Create(*fname)
- if err != nil {
- log.Fatal(err)
- }
- defer fout.Close()
-
- gzw := gzip.NewWriter(fout)
- defer gzw.Close()
-
- tw := tar.NewWriter(gzw)
- defer tw.Close()
-
- dir, err := ioutil.TempDir("", "appsluggr")
- if err != nil {
- log.Fatal(err)
- }
-
- defer os.RemoveAll(dir) // clean up
-
- os.MkdirAll(filepath.Join(dir, "bin"), 0777)
- var procfile, scalefile string
-
- copy.Copy("translations", filepath.Join(dir, "translations"))
- if *web != "" {
- procfile += "web: /app/bin/web\n"
- scalefile += fmt.Sprintf("web=%d", *webScale)
- Copy(*web, filepath.Join(dir, "bin", "web"))
-
- }
- if *worker != "" {
- procfile += "worker: /app/bin/worker\n"
- scalefile += fmt.Sprintf("worker=%d", *workerScale)
- Copy(*worker, filepath.Join(dir, "bin", "worker"))
- }
-
- os.MkdirAll(filepath.Join(dir, ".config"), 0777)
-
- err = ioutil.WriteFile(filepath.Join(dir, ".buildpacks"), []byte("https://github.com/ryandotsmith/null-buildpack"), 0666)
- if err != nil {
- log.Fatal(err)
- }
- err = ioutil.WriteFile(filepath.Join(dir, "DOKKU_SCALE"), []byte(scalefile), 0666)
- if err != nil {
- log.Fatal(err)
- }
- err = ioutil.WriteFile(filepath.Join(dir, "Procfile"), []byte(procfile), 0666)
- if err != nil {
- log.Fatal(err)
- }
-
- hash, err := dirhash.HashDir(dir, os.Args[0], dirhash.Hash1)
- if err != nil {
- log.Fatal(err)
- }
-
- log.Printf("hash: %s", hash)
- gzw.Comment = hash
-
- filepath.Walk(dir, func(file string, fi os.FileInfo, err error) error {
- // return on any error
- if err != nil {
- log.Printf("got error on %s: %v", file, err)
- return err
- }
-
- if fi.IsDir() {
- return nil // not a file. ignore.
- }
-
- // create a new dir/file header
- header, err := tar.FileInfoHeader(fi, fi.Name())
- if err != nil {
- return err
- }
-
- // update the name to correctly reflect the desired destination when untaring
- header.Name = strings.TrimPrefix(strings.Replace(file, dir, "", -1), string(filepath.Separator))
-
- // write the header
- if err := tw.WriteHeader(header); err != nil {
- return err
- }
-
- // return on non-regular files (thanks to [kumo](https://medium.com/@komuw/just-like-you-did-fbdd7df829d3) for this suggested update)
- if !fi.Mode().IsRegular() {
- return nil
- }
-
- // open files for taring
- f, err := os.Open(file)
- if err != nil {
- return err
- }
-
- // copy file data into tar writer
- if _, err := io.Copy(tw, f); err != nil {
- return err
- }
-
- // manually close here after each file operation; defering would cause each file close
- // to wait until all operations have completed.
- f.Close()
-
- return nil
- })
-}
-
-// Copy the src file to dst. Any existing file will be overwritten and will not
-// copy file attributes.
-func Copy(src, dst string) error {
- in, err := os.Open(src)
- if err != nil {
- return err
- }
- defer in.Close()
- st, err := in.Stat()
- if err != nil {
- return err
- }
-
- out, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY, st.Mode())
- if err != nil {
- return err
- }
- defer out.Close()
-
- _, err = io.Copy(out, in)
- if err != nil {
- return err
- }
- return out.Close()
-}
diff --git a/cmd/dnsd/Dockerfile b/cmd/dnsd/Dockerfile
deleted file mode 100644
index 7cd22bf..0000000
--- a/cmd/dnsd/Dockerfile
+++ /dev/null
@@ -1,11 +0,0 @@
-ARG X_VERSION
-
-FROM xena/xperimental:$X_VERSION as build
-FROM xena/alpine
-
-ENV PORT 53
-ENV FORWARD_SERVER 1.1.1.1:53
-EXPOSE 53/udp
-
-COPY --from=build /usr/local/bin/dnsd /usr/local/bin/dnsd
-CMD /usr/local/bin/dnsd
diff --git a/cmd/dnsd/README.md b/cmd/dnsd/README.md
deleted file mode 100644
index cb3921c..0000000
--- a/cmd/dnsd/README.md
+++ /dev/null
@@ -1,88 +0,0 @@
-# dnsd
-
-A custom [DNS](https://en.wikipedia.org/wiki/Domain_Name_System) server for my network. DNS zone files are dynamically downloaded on
-startup and are continuously monitored for changes. When the DNS zone is changed,
-the service reloads it.
-
-I primarily use this to give myself a limited form of piHole DNS adblocking, as
-well as serving my [home network services](https://home.cetacean.club).
-
-This is related to my [WireGuard Site to Site VPN](https://christine.website/blog/site-to-site-wireguard-part-1-2019-04-02)
-project.
-
-## How to Configure `dnsd`
-
-`dnsd` relies on [RFC 1035](https://tools.ietf.org/html/rfc1035) zone files. This
-is a file that looks roughly like this:
-
-```rfc1035
-$TTL 60
-$ORIGIN pele.
-@ IN SOA oho.pele. some@email.address. (
- 2019040601 ; serial number YYYYMMDDNN
- 28800 ; Refresh
- 7200 ; Retry
- 864000 ; Expire
- 60 ; Minimum DNS TTL
- )
- IN NS oho.pele.
-
-oho IN A 10.55.0.1
-1.0.55.10.in-addr.arpa. IN PTR oho.pele.
-
-;; apps
-prometheus IN CNAME oho.pele.
-grafana IN CNAME oho.pele.
-```
-
-Put this file in a publicly available place and then set its URL as a
-`-zone-file` in the command line configuration. This file will be monitored
-every minute for changes (via the proxy of the ETag of the HTTP responses).
-
-If you need to change the DNS forwarding server, set the value of the environment
-variable `FORWARD_SERVER` or the command line flag `-forward-server`.
-
-## Installation
-
-### Docker
-
-```console
-$ export DNSD_VERSION=v1.0.3
-$ docker run --name dnsd -p 53:53/udp -dit --restart always xena/dnsd:$DNSD_VERSION \
- dnsd -zone-url https://domain.hostname.tld/path/to/your.zone \
- -zone-url https://domain.hostname.tld/path/to/adblock.zone \
- -forward-server 1.1.1.1:53
-```
-
-### From Git with systemd
-
-```console
-$ go get -u -v github.com/Xe/x/cmd/dnsd@latest
-$ GOBIN=$(pwd) go install github.com/Xe/x/cmd/dnsd
-$ sudo cp dnsd /usr/local/bin/dnsd
-<edit dnsd.service as needed>
-$ sudo cp dnsd.service /etc/systemd/system/dnsd.service
-$ sudo systemctl daemon-reload
-$ sudo systemctl start dnsd
-$ sudo systemctl status dnsd
-$ sudo systemctl enable dnsd
-```
-
-## Testing
-
-```console
-$ dig @127.0.0.1 google.com
-$ dig @127.0.0.1 oho.pele
-```
-
-## Support
-
-If you need help with this, please [contact](https://christine.website/contact) me.
-This is fairly simplistic software. If you need anything more, I'd suggest using
-[CoreDNS](https://coredns.io) or similar.
-
-If you like this software, please consider donating on [Patreon](https://www.patreon.com/cadey)
-or [Ko-Fi](https://www.ko-fi.com/christinedodrill). I use this software daily on my personal
-network to service most of my devices.
-
-Thanks and be well.
diff --git a/cmd/dnsd/dnsd.conf b/cmd/dnsd/dnsd.conf
deleted file mode 100644
index e490d13..0000000
--- a/cmd/dnsd/dnsd.conf
+++ /dev/null
@@ -1,7 +0,0 @@
-port 5900
-forward-server 1.1.1.1:53
-
-zone-url (
- https://xena.greedo.xeserv.us/files/akua.zone
- https://xena.greedo.xeserv.us/files/adblock.zone
-) \ No newline at end of file
diff --git a/cmd/dnsd/dnsd.service b/cmd/dnsd/dnsd.service
deleted file mode 100644
index 73add3d..0000000
--- a/cmd/dnsd/dnsd.service
+++ /dev/null
@@ -1,12 +0,0 @@
-[Unit]
-Description=dnsd
-
-[Service]
-Environment=PORT=53
-Environment=FORWARD_SERVER=1.1.1.1:53
-ExecStart=/usr/local/bin/dnsd -zone-file https://host.domain.tld/path/to/your.zone -zone-file https://host.domain.tld/path/to/adblock.zone
-Restart=always
-RestartSec=1s
-
-[Install]
-WantedBy=multi-user.target
diff --git a/cmd/dnsd/main.go b/cmd/dnsd/main.go
deleted file mode 100644
index c84a54b..0000000
--- a/cmd/dnsd/main.go
+++ /dev/null
@@ -1,169 +0,0 @@
-// Command dnsd is a simple DNS server for my network. It has O(n) lookup times.
-package main
-
-import (
- "bufio"
- "flag"
- "log"
- "net/http"
- "os"
- "os/signal"
- "syscall"
- "time"
-
- "github.com/miekg/dns"
- "github.com/mmikulicic/stringlist"
- "within.website/x/internal"
-)
-
-var (
- port = flag.String("port", "53", "UDP port to listen on for DNS")
- server = flag.String("forward-server", "1.1.1.1:53", "forward DNS server")
-
- zoneURLs = stringlist.Flag("zone-url", "DNS zonefiles to load")
-)
-
-var (
- defaultZoneURLS = []string{
- "https://xena.greedo.xeserv.us/files/akua.zone",
- "https://xena.greedo.xeserv.us/files/adblock.zone",
- }
-)
-
-func monitorURLs(urls []string) {
- etags := make(map[string]string)
-
- t := time.NewTicker(time.Minute)
- defer t.Stop()
-
- for {
- select {
- case <-t.C:
- for _, urli := range urls {
- resp, err := http.Get(urli)
- if err != nil {
- panic(err)
- }
-
- et := resp.Header.Get("ETag")
-
- ot, ok := etags[urli]
- if !ok {
- log.Printf("stored %s:%s", urli, et)
- etags[urli] = et
- }
- if ok && et != ot {
- log.Fatalf("url %s has new etag %s and wanted old etag %s", urli, et, ot)
- }
- }
- }
- }
-}
-
-func main() {
- internal.HandleStartup()
-
- if len(*zoneURLs) == 0 {
- *zoneURLs = defaultZoneURLS
- }
-
- go monitorURLs(*zoneURLs)
-
- for _, zurl := range *zoneURLs {
- log.Printf("conf: -zone-url=%s", zurl)
- }
- log.Printf("conf: -port=%s", *port)
- log.Printf("conf: -forward-server=%s", *server)
-
- rrs := []dns.RR{}
- ns := []dns.RR{}
-
- for _, zurl := range *zoneURLs {
- resp, err := http.Get(zurl)
- if err != nil {
- panic(err)
- }
-
- reader := bufio.NewReaderSize(resp.Body, 2048)
-
- var i int
- zp := dns.NewZoneParser(reader, "", zurl)
- for rr, ok := zp.Next(); ok; rr, ok = zp.Next() {
- rrs = append(rrs, rr)
-
- if rr.Header().Rrtype == dns.TypeNS {
- ns = append(ns, rr)
- }
-
- i++
- }
-
- if zp.Err() != nil {
- panic(zp.Err())
- }
-
- resp.Body.Close()
-
- log.Printf("%s: %d records", zurl, i)
- }
-
- dns.HandleFunc(".", func(w dns.ResponseWriter, r *dns.Msg) {
- m := new(dns.Msg)
- m.SetReply(r)
- m.Authoritative = true
-
- for _, q := range r.Question {
- answers := []dns.RR{}
- for _, rr := range rrs {
- rh := rr.Header()
-
- if rh.Rrtype == dns.TypeCNAME && q.Name == rh.Name {
- answers = append(answers, rr)
-
- for _, a := range resolver("127.0.0.1:"+*port, rr.(*dns.CNAME).Target, q.Qtype) {
- answers = append(answers, a)
- }
- }
-
- if q.Name == rh.Name && q.Qtype == rh.Rrtype && q.Qclass == rh.Class {
- answers = append(answers, rr)
- }
- }
- if len(answers) == 0 && *server != "" {
- for _, a := range resolver(*server, q.Name, q.Qtype) {
- answers = append(answers, a)
- }
- } else {
- m.Ns = ns
- }
- for _, a := range answers {
- m.Answer = append(m.Answer, a)
- }
- }
- w.WriteMsg(m)
- })
-
- go func() {
- srv := &dns.Server{Addr: ":" + *port, Net: "udp"}
- if err := srv.ListenAndServe(); err != nil {
- log.Fatalf("Failed to set udp listener %s\n", err.Error())
- }
- }()
-
- sig := make(chan os.Signal)
- signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
- s := <-sig
- log.Fatalf("Signal (%v) received, stopping\n", s)
-}
-
-func resolver(server, fqdn string, r_type uint16) []dns.RR {
- m1 := new(dns.Msg)
- m1.Id = dns.Id()
- m1.SetQuestion(fqdn, r_type)
-
- in, err := dns.Exchange(m1, server)
- if err == nil {
- return in.Answer
- }
- return []dns.RR{}
-}
diff --git a/cmd/genua/main.go b/cmd/genua/main.go
deleted file mode 100644
index 1ff8516..0000000
--- a/cmd/genua/main.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// Command genua generates an example user agent.
-package main
-
-import (
- "flag"
- "fmt"
- "log"
-
- "within.website/x/web/useragent"
-)
-
-func main() {
- flag.Parse()
-
- if flag.NArg() != 2 {
- log.Fatal("usage: genua <prefix> <infoURL>")
- }
-
- fmt.Println(useragent.GenUserAgent(flag.Arg(0), flag.Arg(1)))
-}
diff --git a/cmd/minipaas/main.go b/cmd/minipaas/main.go
deleted file mode 100644
index 41ca72a..0000000
--- a/cmd/minipaas/main.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// Command minipaas is a simple client for minipaas.xeserv.us. This is not useful without access to that server.
-package main
-
-import (
- "flag"
- "log"
- "strings"
-
- "within.website/x/internal"
- "within.website/x/internal/minipaas"
-)
-
-func main() {
- flag.Parse()
- internal.HandleStartup()
-
- err := minipaas.Exec(strings.Join(flag.Args(), " "))
- if err != nil {
- log.Fatal(err)
- }
-}
diff --git a/cmd/thumber/in/XjScp8a.png b/cmd/thumber/in/XjScp8a.png
deleted file mode 100644
index a9ec6df..0000000
--- a/cmd/thumber/in/XjScp8a.png
+++ /dev/null
Binary files differ
diff --git a/cmd/thumber/in/lB4ICS3.png b/cmd/thumber/in/lB4ICS3.png
deleted file mode 100644
index 850bf28..0000000
--- a/cmd/thumber/in/lB4ICS3.png
+++ /dev/null
Binary files differ
diff --git a/cmd/thumber/in/oaw79y9.jpg b/cmd/thumber/in/oaw79y9.jpg
deleted file mode 100644
index 2ab4cb9..0000000
--- a/cmd/thumber/in/oaw79y9.jpg
+++ /dev/null
Binary files differ
diff --git a/cmd/thumber/main.go b/cmd/thumber/main.go
deleted file mode 100644
index bd67130..0000000
--- a/cmd/thumber/main.go
+++ /dev/null
@@ -1,58 +0,0 @@
-// Command thumber creates 256x256 thumbnails for a folder/pile of them.
-package main
-
-import (
- "flag"
- "log"
- "os"
- "path/filepath"
- "strings"
-
- "github.com/disintegration/imaging"
- "within.website/x/internal"
-)
-
-var (
- dirToWalk = flag.String("walkdir", "./in", "directory to walk and generate thumbnails for")
-)
-
-func main() {
- internal.HandleStartup()
-
- err := filepath.Walk(*dirToWalk, makeThumbnail)
- if err != nil {
- log.Fatal(err)
- }
-}
-
-func makeThumbnail(fname string, info os.FileInfo, err error) error {
- if info.IsDir() {
- return nil
- }
-
- if strings.HasSuffix(fname, ".thumb.png") {
- return nil
- }
-
- if strings.HasSuffix(fname, ".html") {
- return nil
- }
-
- _, err = os.Stat("thumbs/" + filepath.Base(fname) + ".thumb.png")
- if err == nil {
- log.Printf("skipping %s", fname)
- return nil
- }
-
- log.Printf("Starting to open %s", fname)
-
- img, err := imaging.Open(fname)
- if err != nil {
- return err
- }
-
- croppedImage := imaging.Thumbnail(img, 256, 256, imaging.Lanczos)
- err = imaging.Save(croppedImage, "thumbs/"+filepath.Base(fname)+".thumb.png")
-
- return err
-}
diff --git a/cmd/tlstestd/main.go b/cmd/tlstestd/main.go
deleted file mode 100644
index 8b1489e..0000000
--- a/cmd/tlstestd/main.go
+++ /dev/null
@@ -1,31 +0,0 @@
-// Command tlstestd loads the given TLS cert/key and listens to the given port over HTTPS.
-package main
-
-import (
- "flag"
- "log"
- "net/http"
-
- "within.website/x/internal"
-)
-
-var (
- cert = flag.String("cert", "cert.pem", "TLS cert file")
- key = flag.String("key", "key.pem", "TLS key")
- port = flag.String("port", "2848", "TCP port to listen on")
-)
-
-func helloServer(w http.ResponseWriter, req *http.Request) {
- w.Header().Set("Content-Type", "text/plain")
- w.Write([]byte("Your TLS connection works...or you accepted an invalid cert :)"))
-}
-
-func main() {
- internal.HandleStartup()
-
- http.HandleFunc("/", helloServer)
- err := http.ListenAndServeTLS(":"+*port, *cert, *key, nil)
- if err != nil {
- log.Fatal("ListenAndServe: ", err)
- }
-}
diff --git a/cmd/tor2web/main.go b/cmd/tor2web/main.go
deleted file mode 100644
index b6a03e6..0000000
--- a/cmd/tor2web/main.go
+++ /dev/null
@@ -1,58 +0,0 @@
-// Command tor2web is a simple caching proxy to tor onion sites.
-package main
-
-import (
- "context"
- "flag"
- "log"
- "net/http"
- "net/http/httputil"
-
- "github.com/birkelund/boltdbcache"
- "github.com/gregjones/httpcache"
- "golang.org/x/net/proxy"
- "within.website/ln"
- "within.website/ln/opname"
-)
-
-var (
- dbLoc = flag.String("db-loc", "./cache.db", "cache location on disk (boltdb)")
- torSocksAddr = flag.String("tor-socks-addr", "127.0.0.1:9050", "tor socks address")
- httpPort = flag.String("port", "80", "HTTP port")
- httpsPort = flag.String("https-port", "443", "HTTPS port")
- tlsCert = flag.String("tls-cert", "/etc/within/star.onion.cert.pem", "tls cert location on disk")
- tlsKey = flag.String("tls-key", "/etc/within/star.onion.key.pem", "tls key location on disk")
-)
-
-func main() {
- ctx := opname.With(context.Background(), "main")
- // Create a socks5 dialer
- dialer, err := proxy.SOCKS5("tcp", "127.0.0.1:9050", nil, proxy.Direct)
- if err != nil {
- log.Fatal(err)
- }
-
- // Setup HTTP transport
- tr := &http.Transport{
- Dial: dialer.Dial,
- }
-
- c, err := boltdbcache.New(*dbLoc, boltdbcache.WithBucketName("darkweb"))
- if err != nil {
- ln.FatalErr(ctx, err)
- }
-
- ttr := httpcache.NewTransport(c)
- ttr.Transport = tr
-
- rp := &httputil.ReverseProxy{
- Transport: ttr,
- Director: func(r *http.Request) {
- r.URL.Scheme = "http"
- r.URL.Host = r.Host
- },
- }
-
- go ln.FatalErr(ctx, http.ListenAndServe(":"+*httpPort, rp))
- ln.FatalErr(ctx, http.ListenAndServeTLS(":"+*httpsPort, *tlsCert, *tlsKey, rp))
-}
diff --git a/cmd/within.website/build.go b/cmd/within.website/build.go
deleted file mode 100644
index b6dfb4e..0000000
--- a/cmd/within.website/build.go
+++ /dev/null
@@ -1,58 +0,0 @@
-//+build ignore
-
-// Builds and deploys the application to minipaas.
-package main
-
-import (
- "context"
- "flag"
- "log"
- "net/http"
- "os"
-
- "github.com/shurcooL/vfsgen"
- "within.website/x/internal"
- "within.website/x/internal/kahless"
- "within.website/x/internal/yeet"
-)
-
-var (
- genVFS = flag.Bool("gen-vfs", true, "if true, generate VFS")
- deploy = flag.Bool("deploy", true, "if true, deploy to minipaas via kahless")
-)
-
-func main() {
- internal.HandleStartup()
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
-
- if *genVFS {
- err := vfsgen.Generate(http.Dir("./static"), vfsgen.Options{
- PackageName: "main",
- BuildTags: "!dev",
- VariableName: "assets",
- })
- if err != nil {
- log.Fatalln(err)
- }
- }
-
- if *deploy {
- env := append(os.Environ(), []string{"CGO_ENABLED=0", "GOOS=linux"}...)
- yeet.ShouldWork(ctx, env, yeet.WD, "go", "build", "-o=web")
- yeet.ShouldWork(ctx, env, yeet.WD, "appsluggr", "-web=web")
- fin, err := os.Open("slug.tar.gz")
- if err != nil {
- log.Fatal(err)
- }
- defer fin.Close()
-
- fname := "within.website-" + yeet.DateTag + ".tar.gz"
- pubURL, err := kahless.CopyFile(fname, fin)
- if err != nil {
- log.Fatal(err)
- }
-
- log.Println(pubURL)
- }
-}
diff --git a/cmd/xedn/build.go b/cmd/xedn/build.go
index d84e89e..38f6335 100644
--- a/cmd/xedn/build.go
+++ b/cmd/xedn/build.go
@@ -1,6 +1,6 @@
-//+build ignore
+//go:build ignore
-// Builds and deploys the application to minipaas.
+// Builds and deploys the application to fly.io.
package main
import (
@@ -8,6 +8,7 @@ import (
"os"
"within.website/x/internal"
+ "within.website/x/internal/appsluggr"
"within.website/x/internal/yeet"
)
@@ -19,7 +20,8 @@ func main() {
env := append(os.Environ(), []string{"CGO_ENABLED=0", "GOOS=linux"}...)
yeet.ShouldWork(ctx, env, yeet.WD, "go", "build", "-v", "-o=web")
- yeet.ShouldWork(ctx, env, yeet.WD, "appsluggr", "-web=web")
- os.Remove("web")
+ appsluggr.Must("./web", "./slug.tar.gz")
+ os.Remove("./web")
yeet.ShouldWork(ctx, env, yeet.WD, "flyctl", "deploy", "--now")
+ os.Remove("./slug.tar.gz")
}
diff --git a/docs/man1/appsluggr.1 b/docs/man1/appsluggr.1
deleted file mode 100644
index a0f3881..0000000
--- a/docs/man1/appsluggr.1
+++ /dev/null
@@ -1,113 +0,0 @@
-.Dd December 09, 2018
-.Dt APPSLUGGR 1 URM
-
-
-.Sh NAME
-.Nm appsluggr
-.Nd appsluggr packages a precompiled binary application as a Heroku style slug for use with Dokku.
-
-
-.Sh SYNOPSIS
-.Nm
-
-.Op Fl fname
-.Op Fl license
-.Op Fl web
-.Op Fl web-scale
-.Op Fl worker
-.Op Fl worker-scale
-
-
-.Sh DESCRIPTION
-.Nm
-is a small tool to package
-.Li GOOS=linux GOARCH=amd64
-binaries for consumption on
-.Li hyperlink: http://dokku.viewdocs.io/dokku/ Dokku
-.
-
-.Bl -tag -width " " -offset indent -compact
-
-.It Fl fname
-The filename to write the resulting slug to.
-
-The default value for this is
-.Li slug.tar.gz
-.
-
-.It Fl license
-If set, the tool will show its software license details and then exit.
-
-.It Fl web
-The path to the binary for the web process.
-
-One of
-.Fl web
-or
-.Fl worker
-must be set.
-
-.It Fl web-scale
-The default scale for web process if defined.
-
-The default value for this is 1.
-
-.It Fl worker
-The path to the binary for the worker process.
-One of
-.Fl web
-or
-.Fl worker
-must be set.
-
-.It Fl worker-scale
-The default scale for the worker process if defined.
-
-The default value for this is 1
-
-.El
-
-
-.Sh EXAMPLES
-
-.Li appsluggr
-
-.Li appsluggr -web web
-
-.Li appsluggr -worker ilo-sona
-
-.Li appsluggr -fname foo.tar.gz -web web -worker worker -web-scale 4 -worker-scale 16
-
-
-.Sh IMPLEMENTATION NOTES
-
-.Nm
-when used with
-.Lk hyperlink: http://dokku.viewdocs.io/dokku/ Dokku
-requires the use of the
-.Lk hyperlink: https://github.com/ryandotsmith/null-buildpack Null Buildpack
-as follows:
-
-.Li $ dokku config:set $APP_NAME BUILDPACK_URL=https://github.com/ryandotsmith/null-buildpack
-
-Or
-
-.Li $ ssh dokku@host config:set <see above>
-
-
-.Sh DIAGNOSTICS
-
-.Ex -std appsluggr
-
-
-.Sh SEE ALSO
-
-.Bl -bullet
-
-.It
-.Lk hyperlink: http://dokku.viewdocs.io/dokku/ Dokku
-
-.It
-.Lk hyperlink: https://github.com/ryandotsmith/null-buildpack Null Buildpack
-
-.El
diff --git a/internal/appsluggr/appsluggr.go b/internal/appsluggr/appsluggr.go
new file mode 100644
index 0000000..7a884ae
--- /dev/null
+++ b/internal/appsluggr/appsluggr.go
@@ -0,0 +1,112 @@
+// Package appsluggr packages a given binary into a Heroku-compatible slug.
+package appsluggr
+
+import (
+ "archive/tar"
+ "compress/gzip"
+ "io"
+ "log"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "github.com/otiai10/copy"
+ "github.com/rogpeppe/go-internal/dirhash"
+)
+
+// Must calls Pack and panics on an error.
+//
+// This is useful for using appsluggr from yeet scripts.
+func Must(fname, outFname string) {
+ if err := Pack(fname, outFname); err != nil {
+ log.Panicf("error packing %s into %s: %v", fname, outFname, err)
+ }
+}
+
+// Pack takes a statically linked binary and packs it into a Heroku-compatible slug image
+// at outFname.
+func Pack(fname string, outFname string) error {
+ dir, err := os.MkdirTemp("", "appsluggr")
+ if err != nil {
+ return err
+ }
+ defer os.RemoveAll(dir)
+
+ fout, err := os.Create(outFname)
+ if err != nil {
+ return err
+ }
+ defer fout.Close()
+
+ gzw := gzip.NewWriter(fout)
+ defer gzw.Close()
+
+ tw := tar.NewWriter(gzw)
+ defer tw.Close()
+
+ os.MkdirAll(filepath.Join(dir, "bin"), 0777)
+
+ if err := copy.Copy(fname, filepath.Join(dir, "bin", "main")); err != nil {
+ return err
+ }
+
+ if err := os.WriteFile(filepath.Join(dir, "Procfile"), []byte("web: /app/bin/main\n"), 0777); err != nil {
+ return err
+ }
+
+ hash, err := dirhash.HashDir(dir, os.Args[0], dirhash.Hash1)
+ if err != nil {
+ return err
+ }
+
+ gzw.Comment = hash
+ log.Printf("hash: %s", hash)
+
+ return filepath.Walk(dir, func(file string, fi os.FileInfo, err error) error {
+ // return on any error
+ if err != nil {
+ log.Printf("got error on %s: %v", file, err)
+ return err
+ }
+
+ if fi.IsDir() {
+ return nil // not a file. ignore.
+ }
+
+ // create a new dir/file header
+ header, err := tar.FileInfoHeader(fi, fi.Name())
+ if err != nil {
+ return err
+ }
+
+ // update the name to correctly reflect the desired destination when untaring
+ header.Name = strings.TrimPrefix(strings.Replace(file, dir, "", -1), string(filepath.Separator))
+
+ // write the header
+ if err := tw.WriteHeader(header); err != nil {
+ return err
+ }
+
+ // return on non-regular files (thanks to [kumo](https://medium.com/@komuw/just-like-you-did-fbdd7df829d3) for this suggested update)
+ if !fi.Mode().IsRegular() {
+ return nil
+ }
+
+ // open files for taring
+ f, err := os.Open(file)
+ if err != nil {
+ return err
+ }
+
+ // copy file data into tar writer
+ if _, err := io.Copy(tw, f); err != nil {
+ return err
+ }
+
+ // manually close here after each file operation; defering would cause each file close
+ // to wait until all operations have completed.
+ f.Close()
+
+ return nil
+ })
+}
diff --git a/tor/tor.go b/tor/tor.go
deleted file mode 100644
index a7ad373..0000000
--- a/tor/tor.go
+++ /dev/null
@@ -1,88 +0,0 @@
-// Package tor manages and automates starting a child tor process for exposing TCP services into onionland.
-package tor
-
-import (
- "crypto/rsa"
- "fmt"
- "log"
- "strconv"
- "time"
-
- "github.com/Yawning/bulb"
- "github.com/phayes/freeport"
- "github.com/sycamoreone/orc/tor"
-)
-
-// Config is a wrapper struct for tor configuration.
-type Config struct {
- DataDir string
- HashedControlPassword string
- ClearPassword string
- Timeout time.Duration
-}
-
-// StartTor starts a new instance of tor or doesn't with the reason why.
-func StartTor(cfg Config) (*Tor, error) {
- tc := tor.NewConfig()
- tc.Set("DataDirectory", cfg.DataDir)
- tc.Set("HashedControlPassword", cfg.HashedControlPassword)
- tc.Set("SocksPort", "0")
-
- port, err := freeport.GetFreePort()
- if err != nil {
- return nil, err
- }
-
- tc.Set("ControlPort", fmt.Sprint(port))
-
- tc.Timeout = cfg.Timeout
-
- tcmd, err := tor.NewCmd(tc)
- if err != nil {
- return nil, err
- }
-
- err = tcmd.Start()
- if err != nil {
- return nil, err
- }
-
- log.Println("tor started, sleeping for a few seconds for it to settle...")
- time.Sleep(5 * time.Second)
-
- bc, err := bulb.Dial("tcp", "127.0.0.1:"+strconv.Itoa(port))
- if err != nil {
- return nil, err
- }
-
- err = bc.Authenticate(cfg.ClearPassword)
- if err != nil {
- return nil, err
- }
-
- t := &Tor{
- tc: tc,
- tcmd: tcmd,
- bc: bc,
- }
-
- return t, nil
-}
-
-// Tor is a higher level wrapper to a child tor process
-type Tor struct {
- tc *tor.Config
- tcmd *tor.Cmd
- bc *bulb.Conn
-}
-
-// AddOnion adds an onion service to this machine with the given private key
-// (can be nil for an auto-generated key), virtual onion port and TCP destunation.
-func (t *Tor) AddOnion(pKey *rsa.PrivateKey, virtPort uint16, destination string) (*bulb.OnionInfo, error) {
- return t.bc.AddOnion([]bulb.OnionPortSpec{
- {
- VirtPort: virtPort,
- Target: destination,
- },
- }, pKey, true)
-}