mirror of
https://github.com/DeBrosOfficial/orama.git
synced 2026-03-17 13:06:56 +00:00
224 lines
5.6 KiB
Bash
Executable File
224 lines
5.6 KiB
Bash
Executable File
#!/bin/bash
|
|
# Build Caddy with orama DNS module for linux/amd64
|
|
# Outputs to bin-linux/caddy
|
|
set -e
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
OUTPUT_DIR="$PROJECT_ROOT/bin-linux"
|
|
BUILD_DIR="/tmp/caddy-build-linux"
|
|
MODULE_DIR="$BUILD_DIR/caddy-dns-orama"
|
|
|
|
mkdir -p "$OUTPUT_DIR"
|
|
|
|
# Ensure xcaddy is installed
|
|
if ! command -v xcaddy &> /dev/null; then
|
|
echo "Installing xcaddy..."
|
|
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
|
|
fi
|
|
|
|
# Clean up previous build
|
|
rm -rf "$BUILD_DIR"
|
|
mkdir -p "$MODULE_DIR"
|
|
|
|
# Write go.mod
|
|
cat > "$MODULE_DIR/go.mod" << 'GOMOD'
|
|
module github.com/DeBrosOfficial/caddy-dns-orama
|
|
|
|
go 1.22
|
|
|
|
require (
|
|
github.com/caddyserver/caddy/v2 v2.10.2
|
|
github.com/libdns/libdns v1.1.0
|
|
)
|
|
GOMOD
|
|
|
|
# Write provider.go (the orama DNS provider for ACME DNS-01 challenges)
|
|
cat > "$MODULE_DIR/provider.go" << 'PROVIDERGO'
|
|
// Package orama implements a DNS provider for Caddy that uses the Orama Network
|
|
// gateway's internal ACME API for DNS-01 challenge validation.
|
|
package orama
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/caddyserver/caddy/v2"
|
|
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
|
|
"github.com/libdns/libdns"
|
|
)
|
|
|
|
func init() {
|
|
caddy.RegisterModule(Provider{})
|
|
}
|
|
|
|
// Provider wraps the Orama DNS provider for Caddy.
|
|
type Provider struct {
|
|
// Endpoint is the URL of the Orama gateway's ACME API
|
|
// Default: http://localhost:6001/v1/internal/acme
|
|
Endpoint string `json:"endpoint,omitempty"`
|
|
}
|
|
|
|
// CaddyModule returns the Caddy module information.
|
|
func (Provider) CaddyModule() caddy.ModuleInfo {
|
|
return caddy.ModuleInfo{
|
|
ID: "dns.providers.orama",
|
|
New: func() caddy.Module { return new(Provider) },
|
|
}
|
|
}
|
|
|
|
// Provision sets up the module.
|
|
func (p *Provider) Provision(ctx caddy.Context) error {
|
|
if p.Endpoint == "" {
|
|
p.Endpoint = "http://localhost:6001/v1/internal/acme"
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// UnmarshalCaddyfile parses the Caddyfile configuration.
|
|
func (p *Provider) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
|
|
for d.Next() {
|
|
for d.NextBlock(0) {
|
|
switch d.Val() {
|
|
case "endpoint":
|
|
if !d.NextArg() {
|
|
return d.ArgErr()
|
|
}
|
|
p.Endpoint = d.Val()
|
|
default:
|
|
return d.Errf("unrecognized option: %s", d.Val())
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// AppendRecords adds records to the zone. For ACME, this presents the challenge.
|
|
func (p *Provider) AppendRecords(ctx context.Context, zone string, records []libdns.Record) ([]libdns.Record, error) {
|
|
var added []libdns.Record
|
|
|
|
for _, rec := range records {
|
|
rr := rec.RR()
|
|
if rr.Type != "TXT" {
|
|
continue
|
|
}
|
|
|
|
fqdn := rr.Name + "." + zone
|
|
|
|
payload := map[string]string{
|
|
"fqdn": fqdn,
|
|
"value": rr.Data,
|
|
}
|
|
|
|
body, err := json.Marshal(payload)
|
|
if err != nil {
|
|
return added, fmt.Errorf("failed to marshal request: %w", err)
|
|
}
|
|
|
|
req, err := http.NewRequestWithContext(ctx, "POST", p.Endpoint+"/present", bytes.NewReader(body))
|
|
if err != nil {
|
|
return added, fmt.Errorf("failed to create request: %w", err)
|
|
}
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
client := &http.Client{Timeout: 30 * time.Second}
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return added, fmt.Errorf("failed to present challenge: %w", err)
|
|
}
|
|
resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return added, fmt.Errorf("present failed with status %d", resp.StatusCode)
|
|
}
|
|
|
|
added = append(added, rec)
|
|
}
|
|
|
|
return added, nil
|
|
}
|
|
|
|
// DeleteRecords removes records from the zone. For ACME, this cleans up the challenge.
|
|
func (p *Provider) DeleteRecords(ctx context.Context, zone string, records []libdns.Record) ([]libdns.Record, error) {
|
|
var deleted []libdns.Record
|
|
|
|
for _, rec := range records {
|
|
rr := rec.RR()
|
|
if rr.Type != "TXT" {
|
|
continue
|
|
}
|
|
|
|
fqdn := rr.Name + "." + zone
|
|
|
|
payload := map[string]string{
|
|
"fqdn": fqdn,
|
|
"value": rr.Data,
|
|
}
|
|
|
|
body, err := json.Marshal(payload)
|
|
if err != nil {
|
|
return deleted, fmt.Errorf("failed to marshal request: %w", err)
|
|
}
|
|
|
|
req, err := http.NewRequestWithContext(ctx, "POST", p.Endpoint+"/cleanup", bytes.NewReader(body))
|
|
if err != nil {
|
|
return deleted, fmt.Errorf("failed to create request: %w", err)
|
|
}
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
client := &http.Client{Timeout: 30 * time.Second}
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return deleted, fmt.Errorf("failed to cleanup challenge: %w", err)
|
|
}
|
|
resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return deleted, fmt.Errorf("cleanup failed with status %d", resp.StatusCode)
|
|
}
|
|
|
|
deleted = append(deleted, rec)
|
|
}
|
|
|
|
return deleted, nil
|
|
}
|
|
|
|
// GetRecords returns the records in the zone. Not used for ACME.
|
|
func (p *Provider) GetRecords(ctx context.Context, zone string) ([]libdns.Record, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
// SetRecords sets the records in the zone. Not used for ACME.
|
|
func (p *Provider) SetRecords(ctx context.Context, zone string, records []libdns.Record) ([]libdns.Record, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
// Interface guards
|
|
var (
|
|
_ caddy.Module = (*Provider)(nil)
|
|
_ caddy.Provisioner = (*Provider)(nil)
|
|
_ caddyfile.Unmarshaler = (*Provider)(nil)
|
|
_ libdns.RecordAppender = (*Provider)(nil)
|
|
_ libdns.RecordDeleter = (*Provider)(nil)
|
|
_ libdns.RecordGetter = (*Provider)(nil)
|
|
_ libdns.RecordSetter = (*Provider)(nil)
|
|
)
|
|
PROVIDERGO
|
|
|
|
# Run go mod tidy
|
|
cd "$MODULE_DIR" && go mod tidy
|
|
|
|
# Build with xcaddy
|
|
echo "Building Caddy binary..."
|
|
GOOS=linux GOARCH=amd64 xcaddy build v2.10.2 \
|
|
--with "github.com/DeBrosOfficial/caddy-dns-orama=$MODULE_DIR" \
|
|
--output "$OUTPUT_DIR/caddy"
|
|
|
|
# Cleanup
|
|
rm -rf "$BUILD_DIR"
|
|
echo "✓ Caddy built: bin-linux/caddy"
|