M internal/components/manage.templ => internal/components/manage.templ +1 -1
@@ 4,7 4,7 @@ import "git.src.quest/~liljamo/felu/internal/config"
import "fmt"
func getDomainPattern() string {
- return fmt.Sprintf(".%s", config.FeluConfig.DNSPattern)
+ return fmt.Sprintf(".%s", config.FeluConfig.Domain)
}
func getUpdateACommand() string {
M internal/config/config.go => internal/config/config.go +71 -21
@@ 8,21 8,39 @@
// Package config implements the global program config.
package config
-import "git.src.quest/~liljamo/erya-go/util"
+import (
+ "fmt"
+ "log/slog"
+ "net"
+ "os"
+ "strconv"
+
+ "github.com/miekg/dns"
+)
+
+// TODO: Switch back to erya-go once I've rearchitected it.
+//import "git.src.quest/~liljamo/erya-go/util"
// FeluConfig is a global for accessing the global config.
var FeluConfig *config
type config struct {
+ // Domain, is fqdn'd when read.
+ //
+ // Used for NS records and as DNS pattern.
+ Domain string
+ // IPv4 address to return on A queries for Domain.
+ IPv4 string
+
+ // The name displayed in the frontend.
ServiceName string
- DDNSDomain string
-
+ // The email to return in SOAs (e.g. admin.felu.arpa.), is fqdn'd when read.
SOAEmail string
- // Initial email for the admin user, only used if no admin account (e.g. first boot)
+ // Initial email for the admin user, used if no admin account exists (e.g. first boot).
InitialAdminEmail string
- // Initial password for the admin user, only used if no admin account (e.g. first boot)
+ // Initial password for the admin user, used if no admin account exists (e.g. first boot).
InitialAdminPwd string
LogLevel string
@@ 38,34 56,66 @@ type config struct {
DNSBindIP string
DNSBindPort int32
- // Domain pattern, no leading dot, but with trailing dot
- DNSPattern string
}
// InitConfig initializes the global program config from environment variables.
func InitConfig() {
+ ipv4 := net.ParseIP(loadEnvStr("FELU_IPV4")).To4()
+ if ipv4 == nil {
+ panic("Invalid IPv4")
+ }
+
FeluConfig = &config{
- ServiceName: util.LoadEnvStr("FELU_SERVICE_NAME", "FeluDDNS"),
+ Domain: dns.Fqdn(loadEnvStr("FELU_DOMAIN")),
+ IPv4: ipv4.String(),
+
+ ServiceName: loadEnvStrDef("FELU_SERVICE_NAME", "FeluDDNS"),
+
+ SOAEmail: dns.Fqdn(loadEnvStr("FELU_SOA_EMAIL")),
- // FIXME: panic without this, should do same for many of these
- DDNSDomain: util.LoadEnvStr("FELU_DDNS_DOMAIN", "ddns.staging.fuckdns.org"),
- APIUrl: util.LoadEnvStr("FELU_API_URL", "MUST_SET"),
+ InitialAdminEmail: loadEnvStrDef("FELU_INITIAL_ADMIN_EMAIL", "admin@example.com"),
+ InitialAdminPwd: loadEnvStrDef("FELU_INITIAL_ADMIN_PWD", "feluadmin"),
- SOAEmail: util.LoadEnvStr("FELU_SOA_EMAIL", "admin.felu.arpa"),
+ LogLevel: loadEnvStrDef("FELU_LOG_LEVEL", "info"),
- InitialAdminEmail: util.LoadEnvStr("FELU_INITIAL_ADMIN_EMAIL", "admin@example.com"),
- InitialAdminPwd: util.LoadEnvStr("FELU_INITIAL_ADMIN_PWD", "feluadmin"),
+ DataDir: loadEnvStrDef("FELU_DB_PATH", "/var/felu/"),
- LogLevel: util.LoadEnvStr("FELU_LOG_LEVEL", "info"),
+ FrontendBindAddr: loadEnvStrDef("FELU_FRONTEND_BIND_ADDR", "0.0.0.0:8080"),
- DataDir: util.LoadEnvStr("FELU_DB_PATH", "/var/felu/"),
+ APIUrl: loadEnvStr("FELU_API_URL"),
+ APIBindAddr: loadEnvStrDef("FELU_API_BIND_ADDR", "0.0.0.0:8081"),
- FrontendBindAddr: util.LoadEnvStr("FELU_FRONTEND_BIND_ADDR", "0.0.0.0:8080"),
+ DNSBindIP: loadEnvStrDef("FELU_DNS_BIND_IP", "0.0.0.0"),
+ DNSBindPort: loadEnvInt32Def("FELU_DNS_BIND_PORT", 53),
+ }
+}
- APIBindAddr: util.LoadEnvStr("FELU_API_BIND_ADDR", "0.0.0.0:8081"),
+func loadEnvStr(key string) string {
+ value, found := os.LookupEnv(key)
+ if found {
+ return value
+ }
+ panic(fmt.Sprintf("Env var '%s' not found", key))
+}
+
+func loadEnvStrDef(key string, def string) string {
+ value, found := os.LookupEnv(key)
+ if found {
+ return value
+ }
+ slog.Warn("Env var not set, using default", slog.String("key", key), slog.String("def", def))
+ return def
+}
- DNSBindIP: util.LoadEnvStr("FELU_DNS_BIND_IP", "0.0.0.0"),
- DNSBindPort: util.LoadEnvInt32("FELU_DNS_BIND_PORT", 53),
- DNSPattern: util.LoadEnvStr("FELU_DNS_PATTERN", "."),
+func loadEnvInt32Def(key string, def int32) int32 {
+ value, found := os.LookupEnv(key)
+ if found {
+ res, err := strconv.ParseInt(value, 10, 32)
+ if err != nil {
+ panic(fmt.Sprintf("Couldn't parse env var '%s' into an integer", key))
+ }
+ return int32(res)
}
+ slog.Warn("Env var not set, using default", slog.String("key", key), slog.Int("def", int(def)))
+ return def
}
M internal/dns/query.go => internal/dns/query.go +15 -11
@@ 65,20 65,22 @@ func handleARecord(q *dns.Question, m *dns.Msg, r *dns.Msg) {
}
func handleNSRecord(q *dns.Question, m *dns.Msg, r *dns.Msg) {
+ qName := strings.ToLower(q.Name)
+
ns := &dns.NS{
Hdr: dns.RR_Header{Name: q.Name, Rrtype: dns.TypeNS, Class: dns.ClassINET, Ttl: 86400},
- Ns: dns.Fqdn(config.FeluConfig.DDNSDomain),
+ Ns: config.FeluConfig.Domain,
}
- // "Root" DDNS domain NS.
- if q.Name == dns.Fqdn(config.FeluConfig.DDNSDomain) {
+ // "Root" Domain NS.
+ if qName == config.FeluConfig.Domain {
m.Answer = append(m.Answer, ns)
return
}
- if index := strings.IndexByte(q.Name, '.'); index >= 0 {
+ if index := strings.IndexByte(qName, '.'); index >= 0 {
// FIXME: other way of checking that the domain exists
- _, err := db.FetchDomainARecord(strings.ToLower(q.Name[:index]))
+ _, err := db.FetchDomainARecord(qName[:index])
if err != nil {
m.SetRcode(r, dns.RcodeNameError)
} else {
@@ 90,10 92,12 @@ func handleNSRecord(q *dns.Question, m *dns.Msg, r *dns.Msg) {
}
func handleSOARecord(q *dns.Question, m *dns.Msg, r *dns.Msg) {
+ qName := strings.ToLower(q.Name)
+
soa := &dns.SOA{
Hdr: dns.RR_Header{Name: q.Name, Rrtype: dns.TypeSOA, Class: dns.ClassINET, Ttl: 0},
- Ns: dns.Fqdn(config.FeluConfig.DDNSDomain),
- Mbox: dns.Fqdn(config.FeluConfig.SOAEmail),
+ Ns: config.FeluConfig.Domain,
+ Mbox: config.FeluConfig.SOAEmail,
Serial: 2024100301,
Refresh: 86400,
Retry: 7200,
@@ 101,15 105,15 @@ func handleSOARecord(q *dns.Question, m *dns.Msg, r *dns.Msg) {
Minttl: 172800,
}
- // "Root" DDNS domain SOA.
- if q.Name == dns.Fqdn(config.FeluConfig.DDNSDomain) {
+ // "Root" Domain SOA.
+ if qName == config.FeluConfig.Domain {
m.Answer = append(m.Answer, soa)
return
}
- if index := strings.IndexByte(q.Name, '.'); index >= 0 {
+ if index := strings.IndexByte(qName, '.'); index >= 0 {
// FIXME: other way of checking that the domain exists
- _, err := db.FetchDomainARecord(strings.ToLower(q.Name[:index]))
+ _, err := db.FetchDomainARecord(qName[:index])
if err != nil {
m.SetRcode(r, dns.RcodeNameError)
} else {
M internal/dns/server.go => internal/dns/server.go +1 -1
@@ 15,7 15,7 @@ import (
// Run starts the DNS server.
func Run(addr string, net string) error {
- dns.HandleFunc(config.FeluConfig.DNSPattern, handleDNSRequest)
+ dns.HandleFunc(config.FeluConfig.Domain, handleDNSRequest)
server := &dns.Server{
Addr: addr,