Skip to content

Commit deaac9e

Browse files
committed
initial commit
0 parents  commit deaac9e

15 files changed

Lines changed: 1824 additions & 0 deletions

File tree

.github/workflows/release.yml

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
branches: [main]
6+
tags: ["v*"]
7+
8+
permissions:
9+
contents: read
10+
packages: write
11+
12+
jobs:
13+
test:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@v4
17+
- uses: actions/setup-go@v5
18+
with:
19+
go-version: "1.26"
20+
- run: go vet ./...
21+
- run: go test ./... -v
22+
23+
build:
24+
needs: test
25+
runs-on: ubuntu-latest
26+
steps:
27+
- uses: actions/checkout@v4
28+
- uses: actions/setup-go@v5
29+
with:
30+
go-version: "1.26"
31+
- name: Build static binary
32+
run: CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o obsidian-sync .
33+
- name: Upload binary
34+
uses: actions/upload-artifact@v4
35+
with:
36+
name: obsidian-sync
37+
path: obsidian-sync
38+
39+
docker:
40+
needs: build
41+
runs-on: ubuntu-latest
42+
steps:
43+
- uses: actions/checkout@v4
44+
- name: Download binary
45+
uses: actions/download-artifact@v4
46+
with:
47+
name: obsidian-sync
48+
- name: Make binary executable
49+
run: chmod +x obsidian-sync
50+
- name: Copy CA certificates
51+
run: cp /etc/ssl/certs/ca-certificates.crt ca-certificates.crt
52+
- name: Log in to ghcr.io
53+
uses: docker/login-action@v3
54+
with:
55+
registry: ghcr.io
56+
username: ${{ github.actor }}
57+
password: ${{ secrets.GITHUB_TOKEN }}
58+
- name: Docker metadata
59+
id: meta
60+
uses: docker/metadata-action@v5
61+
with:
62+
images: ghcr.io/${{ github.repository }}
63+
tags: |
64+
type=raw,value=latest
65+
type=sha
66+
type=ref,event=tag
67+
- name: Build and push
68+
uses: docker/build-push-action@v6
69+
with:
70+
context: .
71+
push: true
72+
tags: ${{ steps.meta.outputs.tags }}
73+
labels: ${{ steps.meta.outputs.labels }}

Dockerfile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
FROM scratch
2+
COPY obsidian-sync /usr/local/bin/obsidian-sync
3+
COPY ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
4+
EXPOSE 80
5+
ENTRYPOINT ["/usr/local/bin/obsidian-sync"]

LICENSE

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
Elastic License 2.0 (ELv2)
2+
3+
This license applies to the obsidian-sync project.
4+
5+
Copyright © 2025 Albedo Technologies SRL
6+
7+
You may not provide the software to third parties as a hosted or managed
8+
service, where the value of the service derives substantially from the value
9+
of the software or any modification of the software.
10+
11+
You may not move, change, disable, or circumvent the license key functionality
12+
in the software, and you may not remove or obscure any licensing, copyright,
13+
or other notices.
14+
15+
You may not use the software to create a derivative work that is distributed or
16+
used for any commercial purpose that competes with the software. Competing
17+
with the software includes, without limitation, using the software (or
18+
modifications thereof) as part of a product or service that is provided to
19+
third parties for a fee.
20+
21+
You may use, modify, create derivative works, redistribute, and make the
22+
software available to others, provided that you do not violate the above
23+
restrictions.
24+
25+
The software is provided "as-is," without warranty of any kind, express or
26+
implied, including but not limited to warranties of merchantability, fitness
27+
for a particular purpose and non-infringement. In no event shall the authors
28+
or copyright holders be liable for any claim, damages, or other liability,
29+
whether in an action of contract, tort, or otherwise, arising from, out of, or
30+
in connection with the software or the use or other dealings in the software.
31+
32+
This license does not grant you any rights to use the trademarks or trade
33+
names "obsidian-sync" or "Albedo Technologies SRL".

README.md

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
# obsidian-sync
2+
3+
[![Go](https://img.shields.io/badge/Go-1.26-00ADD8?logo=go)](https://go.dev)
4+
[![License: ELv2](https://img.shields.io/badge/License-ELv2-blue)](LICENSE)
5+
[![CI](https://github.com/0xa1bed0/obsidian-sync/actions/workflows/release.yml/badge.svg)](https://github.com/0xa1bed0/obsidian-sync/actions/workflows/release.yml)
6+
[![GHCR](https://img.shields.io/badge/ghcr.io-obsidian--sync-blue?logo=github)](https://ghcr.io/0xa1bed0/obsidian-sync)
7+
8+
S3-compatible server for Obsidian's [Remotely Save](https://github.com/remotely-save/remotely-save) plugin with built-in git auto-commit and push.
9+
10+
## Features
11+
12+
- Implements just enough S3 API for Remotely Save (`PutObject`, `GetObject`, `DeleteObject`, `HeadObject`, `ListObjectsV2`)
13+
- Authenticates requests using AWS Signature V4
14+
- Stores files as plain files on disk — your vault is just a directory
15+
- On any PUT or DELETE, triggers a debounced git commit + push via HTTPS
16+
- Single static binary (~6 MB), no runtime dependencies
17+
- Built-in [go-git](https://github.com/go-git/go-git) — no system `git` required
18+
19+
## Architecture
20+
21+
```mermaid
22+
graph LR
23+
A[iPhone<br>Obsidian + Remotely Save] --> C[Cloudflare<br>HTTPS]
24+
B[MacBook<br>Obsidian + Remotely Save] --> C
25+
C --> D[VPS<br>obsidian-sync]
26+
D --> E[GitHub / GitLab]
27+
```
28+
29+
## Quick start
30+
31+
### Option A: Docker Compose (recommended)
32+
33+
```bash
34+
mkdir -p /opt/obsidian-sync/vault
35+
cd /opt/obsidian-sync
36+
```
37+
38+
Create `docker-compose.yml`:
39+
40+
```yaml
41+
services:
42+
obsidian-sync:
43+
image: ghcr.io/0xa1bed0/obsidian-sync:latest
44+
container_name: obsidian-sync
45+
restart: unless-stopped
46+
ports:
47+
- "80:80"
48+
volumes:
49+
- ./vault:/vault
50+
environment:
51+
- ACCESS_KEY=your-access-key
52+
- SECRET_KEY=your-secret-key
53+
- BUCKET=vault
54+
- REGION=us-east-1
55+
- GIT_REPO=https://github.com/you/obsidian-vault.git
56+
- GIT_TOKEN=ghp_your-personal-access-token
57+
- GIT_BRANCH=main
58+
- DEBOUNCE=10
59+
```
60+
61+
```bash
62+
docker compose up -d
63+
docker logs -f obsidian-sync
64+
```
65+
66+
### Option B: Build from source
67+
68+
```bash
69+
git clone https://github.com/0xa1bed0/obsidian-sync.git
70+
cd obsidian-sync
71+
go build -o obsidian-sync .
72+
./obsidian-sync \
73+
-access-key your-key \
74+
-secret-key your-secret \
75+
-git-repo https://github.com/you/obsidian-vault.git \
76+
-git-token ghp_your-token
77+
```
78+
79+
## Configuration
80+
81+
| Variable | Default | Description |
82+
|----------|---------|-------------|
83+
| `VAULT_DIR` | `/vault` | Directory to store vault files |
84+
| `BUCKET` | `vault` | S3 bucket name |
85+
| `ADDR` | `:80` | Listen address |
86+
| `ACCESS_KEY` | _(none)_ | S3 access key (no auth if empty) |
87+
| `SECRET_KEY` | _(none)_ | S3 secret key |
88+
| `REGION` | `us-east-1` | AWS region for SigV4 |
89+
| `GIT_REPO` | _(none)_ | Git remote HTTPS URL (no push if empty) |
90+
| `GIT_TOKEN` | _(none)_ | Personal access token for HTTPS git auth |
91+
| `GIT_BRANCH` | `main` | Git branch |
92+
| `GIT_USER` | `Obsidian Sync` | Git commit author name |
93+
| `GIT_EMAIL` | `obsidian@sync` | Git commit author email |
94+
| `DEBOUNCE` | `10` | Seconds to debounce before git commit |
95+
| `PULL_INTERVAL` | `60` | Seconds between periodic git pulls (0 to disable) |
96+
97+
All variables can also be passed as CLI flags (e.g. `-access-key`, `-git-token`).
98+
99+
### Creating a GitHub token
100+
101+
1. Go to [Fine-grained tokens](https://github.com/settings/personal-access-tokens/new)
102+
2. **Token name** — e.g. `obsidian-sync`
103+
3. **Expiration** — pick what you're comfortable with
104+
4. **Repository access** — "Only select repositories" → pick your vault repo
105+
5. **Permissions → Repository permissions** — set **Contents** to **Read and write**
106+
6. Click **Generate token** and copy the value (`github_pat_...`)
107+
7. Set it as `GIT_TOKEN` in your `docker-compose.yml`
108+
109+
## Remotely Save setup
110+
111+
1. Obsidian → Settings → Community plugins → Install **Remotely Save**
112+
2. Settings → Remotely Save:
113+
- Remote service: **S3 or S3-compatible**
114+
- Endpoint: `https://sync.yourdomain.com`
115+
- Region: `us-east-1`
116+
- Access Key ID: your access key
117+
- Secret Access Key: your secret key
118+
- Bucket: `vault`
119+
- **Check** "S3 path style" / Force Path Style
120+
- **Disable** "S3 metadata sync" (CopyObject is not implemented)
121+
3. Click **Check Connectivity**
122+
4. Set auto-sync interval (e.g. 5 minutes)
123+
124+
Repeat on every device.
125+
126+
## S3 API coverage
127+
128+
| Operation | Supported | Notes |
129+
|-----------|-----------|-------|
130+
| PutObject | Yes | Triggers git sync |
131+
| GetObject | Yes | |
132+
| HeadObject | Yes | |
133+
| DeleteObject | Yes | Triggers git sync, cleans empty dirs |
134+
| ListObjectsV2 | Yes | Skips `.git` directory |
135+
| HeadBucket | Yes | |
136+
| CopyObject | No | Not needed by Remotely Save |
137+
| Multipart Upload | No | Not needed for typical vault files |
138+
139+
## Contributing
140+
141+
1. Fork the repo
142+
2. Create a feature branch
143+
3. Run `go test ./...` and `go vet ./...`
144+
4. Open a pull request
145+
146+
## License
147+
148+
[Elastic License 2.0 (ELv2)](LICENSE) — Copyright 2025 Albedo Technologies SRL.
149+
150+
You may use, modify, and redistribute this software. You may **not** provide it as a hosted/managed service. See `LICENSE` for full terms.

docker-compose.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
services:
2+
obsidian-sync:
3+
image: ghcr.io/0xa1bed0/obsidian-sync:latest
4+
container_name: obsidian-sync
5+
restart: unless-stopped
6+
ports:
7+
- "80:80"
8+
volumes:
9+
- ./vault:/vault
10+
environment:
11+
- ACCESS_KEY=anatolii
12+
- SECRET_KEY=your-secret-key-here
13+
- BUCKET=vault
14+
- REGION=us-east-1
15+
- GIT_REPO=https://github.com/you/obsidian-vault.git
16+
- GIT_TOKEN=ghp_your-personal-access-token
17+
- GIT_BRANCH=main
18+
- DEBOUNCE=10

go.mod

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
module obsidian-sync
2+
3+
go 1.26.0
4+
5+
require github.com/go-git/go-git/v5 v5.16.5
6+
7+
require (
8+
dario.cat/mergo v1.0.0 // indirect
9+
github.com/Microsoft/go-winio v0.6.2 // indirect
10+
github.com/ProtonMail/go-crypto v1.1.6 // indirect
11+
github.com/cloudflare/circl v1.6.1 // indirect
12+
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
13+
github.com/emirpasic/gods v1.18.1 // indirect
14+
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
15+
github.com/go-git/go-billy/v5 v5.6.2 // indirect
16+
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
17+
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
18+
github.com/kevinburke/ssh_config v1.2.0 // indirect
19+
github.com/pjbgf/sha1cd v0.3.2 // indirect
20+
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
21+
github.com/skeema/knownhosts v1.3.1 // indirect
22+
github.com/xanzy/ssh-agent v0.3.3 // indirect
23+
golang.org/x/crypto v0.45.0 // indirect
24+
golang.org/x/net v0.47.0 // indirect
25+
golang.org/x/sys v0.38.0 // indirect
26+
gopkg.in/warnings.v0 v0.1.2 // indirect
27+
)

0 commit comments

Comments
 (0)