Skip to content

Commit 1faed27

Browse files
authored
Merge pull request #28 from juanfont/sqlite-support-plus-integration
Adding SQLite support
2 parents 619201e + 13b7b3e commit 1faed27

File tree

9 files changed

+84
-13
lines changed

9 files changed

+84
-13
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@
1717
/headscale
1818
config.json
1919
*.key
20+
/db.sqlite

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Suggestions/PRs welcomed!
4444
make
4545
```
4646

47-
2. Get yourself a PostgreSQL DB running (yes, [I know](https://tailscale.com/blog/an-unlikely-database-migration/))
47+
2. (Optional, you can also use SQLite) Get yourself a PostgreSQL DB running
4848

4949
```shell
5050
docker run --name headscale -e POSTGRES_DB=headscale -e \
@@ -55,7 +55,12 @@ Suggestions/PRs welcomed!
5555
```shell
5656
wg genkey > private.key
5757
wg pubkey < private.key > public.key # not needed
58-
cp config.json.example config.json
58+
59+
# Postgres
60+
cp config.json.postgres.example config.json
61+
# or
62+
# SQLite
63+
cp config.json.sqlite.example config.json
5964
```
6065

6166
4. Create a namespace (equivalent to a user in tailscale.com)

api.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,12 +279,14 @@ func (h *Headscale) keepAlive(cancel chan []byte, pollData chan []byte, mKey wgc
279279
return
280280

281281
default:
282+
h.pollMu.Lock()
282283
data, err := h.getMapKeepAliveResponse(mKey, req, m)
283284
if err != nil {
284285
log.Printf("Error generating the keep alive msg: %s", err)
285286
return
286287
}
287288
pollData <- *data
289+
h.pollMu.Unlock()
288290
time.Sleep(60 * time.Second)
289291
}
290292
}

app.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ type Config struct {
2222
PrivateKeyPath string
2323
DerpMap *tailcfg.DERPMap
2424

25+
DBtype string
26+
DBpath string
2527
DBhost string
2628
DBport int
2729
DBname string
@@ -60,11 +62,22 @@ func NewHeadscale(cfg Config) (*Headscale, error) {
6062
return nil, err
6163
}
6264
pubKey := privKey.Public()
65+
66+
var dbString string
67+
switch cfg.DBtype {
68+
case "postgres":
69+
dbString = fmt.Sprintf("host=%s port=%d dbname=%s user=%s password=%s sslmode=disable", cfg.DBhost,
70+
cfg.DBport, cfg.DBname, cfg.DBuser, cfg.DBpass)
71+
case "sqlite3":
72+
dbString = cfg.DBpath
73+
default:
74+
return nil, errors.New("Unsupported DB")
75+
}
76+
6377
h := Headscale{
64-
cfg: cfg,
65-
dbType: "postgres",
66-
dbString: fmt.Sprintf("host=%s port=%d dbname=%s user=%s password=%s sslmode=disable", cfg.DBhost,
67-
cfg.DBport, cfg.DBname, cfg.DBuser, cfg.DBpass),
78+
cfg: cfg,
79+
dbType: cfg.DBtype,
80+
dbString: dbString,
6881
privateKey: privKey,
6982
publicKey: &pubKey,
7083
}

cmd/headscale/cli/utils.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ type ErrorOutput struct {
2222
func absPath(path string) string {
2323
// If a relative path is provided, prefix it with the the directory where
2424
// the config file was found.
25-
if (path != "") && !strings.HasPrefix(path, "/") {
25+
if (path != "") && !strings.HasPrefix(path, string(os.PathSeparator)) {
2626
dir, _ := filepath.Split(viper.ConfigFileUsed())
2727
if dir != "" {
28-
path = dir + "/" + path
28+
path = filepath.Join(dir, path)
2929
}
3030
}
3131
return path
@@ -43,6 +43,8 @@ func getHeadscaleApp() (*headscale.Headscale, error) {
4343
PrivateKeyPath: absPath(viper.GetString("private_key_path")),
4444
DerpMap: derpMap,
4545

46+
DBtype: viper.GetString("db_type"),
47+
DBpath: absPath(viper.GetString("db_path")),
4648
DBhost: viper.GetString("db_host"),
4749
DBport: viper.GetInt("db_port"),
4850
DBname: viper.GetString("db_name"),

cmd/headscale/headscale_test.go

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func (s *Suite) TearDownSuite(c *check.C) {
2727

2828
}
2929

30-
func (*Suite) TestConfigLoading(c *check.C) {
30+
func (*Suite) TestPostgresConfigLoading(c *check.C) {
3131
tmpDir, err := ioutil.TempDir("", "headscale")
3232
if err != nil {
3333
c.Fatal(err)
@@ -40,7 +40,7 @@ func (*Suite) TestConfigLoading(c *check.C) {
4040
}
4141

4242
// Symlink the example config file
43-
err = os.Symlink(filepath.Clean(path+"/../../config.json.example"), filepath.Join(tmpDir, "config.json"))
43+
err = os.Symlink(filepath.Clean(path+"/../../config.json.postgres.example"), filepath.Join(tmpDir, "config.json"))
4444
if err != nil {
4545
c.Fatal(err)
4646
}
@@ -50,14 +50,47 @@ func (*Suite) TestConfigLoading(c *check.C) {
5050
c.Assert(err, check.IsNil)
5151

5252
// Test that config file was interpreted correctly
53-
c.Assert(viper.GetString("server_url"), check.Equals, "http://192.168.1.12:8000")
53+
c.Assert(viper.GetString("server_url"), check.Equals, "http://127.0.0.1:8000")
5454
c.Assert(viper.GetString("listen_addr"), check.Equals, "0.0.0.0:8000")
5555
c.Assert(viper.GetString("derp_map_path"), check.Equals, "derp.yaml")
56+
c.Assert(viper.GetString("db_type"), check.Equals, "postgres")
5657
c.Assert(viper.GetString("db_port"), check.Equals, "5432")
5758
c.Assert(viper.GetString("tls_letsencrypt_hostname"), check.Equals, "")
5859
c.Assert(viper.GetString("tls_letsencrypt_challenge_type"), check.Equals, "HTTP-01")
5960
}
6061

62+
func (*Suite) TestSqliteConfigLoading(c *check.C) {
63+
tmpDir, err := ioutil.TempDir("", "headscale")
64+
if err != nil {
65+
c.Fatal(err)
66+
}
67+
defer os.RemoveAll(tmpDir)
68+
69+
path, err := os.Getwd()
70+
if err != nil {
71+
c.Fatal(err)
72+
}
73+
74+
// Symlink the example config file
75+
err = os.Symlink(filepath.Clean(path+"/../../config.json.sqlite.example"), filepath.Join(tmpDir, "config.json"))
76+
if err != nil {
77+
c.Fatal(err)
78+
}
79+
80+
// Load example config, it should load without validation errors
81+
err = loadConfig(tmpDir)
82+
c.Assert(err, check.IsNil)
83+
84+
// Test that config file was interpreted correctly
85+
c.Assert(viper.GetString("server_url"), check.Equals, "http://127.0.0.1:8000")
86+
c.Assert(viper.GetString("listen_addr"), check.Equals, "0.0.0.0:8000")
87+
c.Assert(viper.GetString("derp_map_path"), check.Equals, "derp.yaml")
88+
c.Assert(viper.GetString("db_type"), check.Equals, "sqlite3")
89+
c.Assert(viper.GetString("db_path"), check.Equals, "db.sqlite")
90+
c.Assert(viper.GetString("tls_letsencrypt_hostname"), check.Equals, "")
91+
c.Assert(viper.GetString("tls_letsencrypt_challenge_type"), check.Equals, "HTTP-01")
92+
}
93+
6194
func writeConfig(c *check.C, tmpDir string, configYaml []byte) {
6295
// Populate a custom config file
6396
configFile := filepath.Join(tmpDir, "config.yaml")
@@ -89,7 +122,7 @@ func (*Suite) TestTLSConfigValidation(c *check.C) {
89122
fmt.Println(tmp)
90123

91124
// Check configuration validation errors (2)
92-
configYaml = []byte("---\nserver_url: \"http://192.168.1.12:8000\"\ntls_letsencrypt_hostname: \"example.com\"\ntls_letsencrypt_challenge_type: \"TLS-ALPN-01\"")
125+
configYaml = []byte("---\nserver_url: \"http://127.0.0.1:8000\"\ntls_letsencrypt_hostname: \"example.com\"\ntls_letsencrypt_challenge_type: \"TLS-ALPN-01\"")
93126
writeConfig(c, tmpDir, configYaml)
94127
err = loadConfig(tmpDir)
95128
c.Assert(err, check.NotNil)
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
{
2-
"server_url": "http://192.168.1.12:8000",
2+
"server_url": "http://127.0.0.1:8000",
33
"listen_addr": "0.0.0.0:8000",
44
"private_key_path": "private.key",
55
"derp_map_path": "derp.yaml",
6+
"db_type": "postgres",
67
"db_host": "localhost",
78
"db_port": 5432,
89
"db_name": "headscale",

config.json.sqlite.example

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"server_url": "http://127.0.0.1:8000",
3+
"listen_addr": "0.0.0.0:8000",
4+
"private_key_path": "private.key",
5+
"derp_map_path": "derp.yaml",
6+
"db_type": "sqlite3",
7+
"db_path": "db.sqlite",
8+
"tls_letsencrypt_hostname": "",
9+
"tls_letsencrypt_cache_dir": ".cache",
10+
"tls_letsencrypt_challenge_type": "HTTP-01",
11+
"tls_cert_path": "",
12+
"tls_key_path": ""
13+
}

db.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
"github.com/jinzhu/gorm"
77
_ "github.com/jinzhu/gorm/dialects/postgres" // sql driver
8+
_ "github.com/jinzhu/gorm/dialects/sqlite" // sql driver
89
)
910

1011
const dbVersion = "1"

0 commit comments

Comments
 (0)