Skip to content

Commit

Permalink
Set up deployment via Kamal
Browse files Browse the repository at this point in the history
Kamal has been integrated into the project for deploying to dev/prod/etc
environments.

The script for creating the deployment config is `deploy.sh` at the root
level of the repo, and requires a single argument describing the
environment being deployed (i.e. `deploy.sh prod`). This script reads
from an environment file matching the specified environment (i.e.
`prod.env`).

The files generated by deploy.sh are used to deploy the app to the
specified servers, allowing seamless deployments without any downtime
for the user.
  • Loading branch information
benbusby committed Dec 18, 2024
1 parent a05a6a9 commit a16992c
Show file tree
Hide file tree
Showing 26 changed files with 264 additions and 89 deletions.
11 changes: 10 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.idea
notes.txt
yeetfile
yeetfile-server
yeetfile-server*
*.enc
test.sh
lipsum-big.txt
Expand All @@ -22,4 +22,13 @@ node_modules/
.pytest_cache/
__pycache__
*test_*.txt
<<<<<<< HEAD
*._*
*.pem
products.json

# Kamal
.kamal
config/*
!config/deploy.yml
!config/deploy.template.yml
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/yeetfile-server /app
RUN chmod +x /app/yeetfile-server
RUN apk add --update curl
EXPOSE 8090

CMD ["/app/yeetfile-server"]
15 changes: 15 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,21 @@ backend: web
cli:
go build -ldflags="-s -w" -tags yeetfile -o yeetfile ./cli

deploy:
GOOS=linux GOARCH=amd64 go build \
-tags yeetfile-server \
-o yeetfile-server-deploy \
./backend
mv yeetfile-server-deploy ansible/roles/yeetfile/files/

deploy_dev: deploy
test -s ./ansible/roles/yeetfile/files/dev.env || { echo "dev.env not in ansible/roles/yeetfile/files -- exiting..."; exit 1; }
ansible-playbook -i ansible/inventory/dev.yml ansible/deploy.yml

deploy_prod: deploy
test -s ./ansible/roles/yeetfile/files/prod.env || { echo "prod.env not in ansible/roles/yeetfile/files -- exiting..."; exit 1; }
ansible-playbook -i ansible/inventory/prod.yml deploy.yml

clean:
rm -f yeetfile-web
rm -f yeetfile
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,9 @@ These are required to be set if you want to use Backblaze B2 to store data that

| Name | Purpose |
| -- | -- |
| B2_BUCKET_ID | The ID of the bucket that will be used for storing uploaded content |
| B2_BUCKET_KEY_ID | The ID of the key used for accessing the B2 bucket |
| B2_BUCKET_KEY | The value of the key used for accessing the B2 bucket |
| `YEETFILE_B2_BUCKET_ID` | The ID of the bucket that will be used for storing uploaded content |
| `YEETFILE_B2_BUCKET_KEY_ID` | The ID of the key used for accessing the B2 bucket |
| `YEETFILE_B2_BUCKET_KEY` | The value of the key used for accessing the B2 bucket |

#### Misc Environment Variables

Expand Down
4 changes: 2 additions & 2 deletions backend/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func PrepCache(fileID string, size int64) {

totalCacheSize, err := utils.CheckDirSize(path)
if err != nil {
utils.Log(fmt.Sprintf("Unable to check cache dir size: %v", err))
log.Printf(fmt.Sprintf("Unable to check cache dir size: %v", err))
return
}

Expand Down Expand Up @@ -265,5 +265,5 @@ func init() {
panic(err)
}

utils.Log(fmt.Sprintf("Caching files to directory: %s", path))
log.Printf("Caching files to directory: %s", path)
}
8 changes: 0 additions & 8 deletions backend/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,11 @@ type StripeBillingConfig struct {
Configured bool
Key string
WebhookSecret string
PortalLink string
}

var stripeBilling = StripeBillingConfig{
Key: os.Getenv("YEETFILE_STRIPE_KEY"),
WebhookSecret: os.Getenv("YEETFILE_STRIPE_WEBHOOK_SECRET"),
PortalLink: os.Getenv("YEETFILE_STRIPE_PORTAL_LINK"),
}

// =============================================================================
Expand All @@ -85,17 +83,11 @@ var stripeBilling = StripeBillingConfig{

type BTCPayBillingConfig struct {
Configured bool
APIKey string
WebhookSecret string
StoreID string
ServerURL string
}

var btcPayBilling = BTCPayBillingConfig{
APIKey: os.Getenv("YEETFILE_BTCPAY_API_KEY"),
WebhookSecret: os.Getenv("YEETFILE_BTCPAY_WEBHOOK_SECRET"),
StoreID: os.Getenv("YEETFILE_BTCPAY_STORE_ID"),
ServerURL: os.Getenv("YEETFILE_BTCPAY_SERVER_URL"),
}

// =============================================================================
Expand Down
30 changes: 28 additions & 2 deletions backend/db/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
_ "github.com/lib/pq"
"io"
"log"
"os"
"sort"
"strconv"
"strings"
Expand All @@ -30,15 +31,40 @@ func init() {
user = utils.GetEnvVar("YEETFILE_DB_USER", "postgres")
password = utils.GetEnvVar("YEETFILE_DB_PASS", "")
dbname = utils.GetEnvVar("YEETFILE_DB_NAME", "yeetfile")
cert = utils.GetEnvVar("YEETFILE_DB_CERT", "")
)

connStr := fmt.Sprintf("postgres://%s:%s@%s:%s/%s?sslmode=disable",
connStr := fmt.Sprintf(
"postgres://%s:%s@%s:%s/%s",
user,
password,
host,
port,
dbname)

if len(cert) > 0 {
cert = strings.ReplaceAll(cert, "\\n", "\n")

certFile, err := os.CreateTemp("", ".*")
if err != nil {
log.Fatalln("Error creating tmp dir for db cert:", err)
}

if _, err = certFile.WriteString(cert); err != nil {
log.Fatalf("Unable to write tmp CA cert file: %v\n", err)
}

if err = certFile.Close(); err != nil {
log.Fatalf("Unable to close tmp CA cert file: %v\n", err)
}

connStr += fmt.Sprintf(
"?sslmode=verify-full&sslrootcert=%s",
certFile.Name())
} else {
connStr += "?sslmode=disable"
}

// Open db connection
var err error
db, err = sql.Open("postgres", connStr)
Expand Down Expand Up @@ -129,7 +155,7 @@ func clearDatabase(id string) {
func TableIDExists(tableName, id string) bool {
rows, err := db.Query(`SELECT * FROM `+tableName+` WHERE id=$1`, id)
if err != nil {
utils.Logf("Error checking for id in table '%s': %v", tableName, err)
log.Printf("Error checking for id in table '%s': %v", tableName, err)
return true
}

Expand Down
4 changes: 3 additions & 1 deletion backend/db/cron.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,9 @@ func (task CronTask) runCronTask() {
}

if !lockAcquired {
log.Printf("'%s' task lock already acquired, skipping", task.Name)
if config.IsDebugMode {
log.Printf("'%s' task lock already acquired, skipping", task.Name)
}
return
}

Expand Down
3 changes: 1 addition & 2 deletions backend/db/folders.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"fmt"
"log"
"time"
"yeetfile/backend/utils"
"yeetfile/shared"
)

Expand Down Expand Up @@ -79,7 +78,7 @@ func insertFolder(id, ownerID string, folder shared.NewVaultFolder, pwFolder boo
func FolderIDExists(id string) bool {
rows, err := db.Query(`SELECT * FROM folders WHERE id=$1`, id)
if err != nil {
utils.Logf("Error checking folder id: %v", err)
log.Printf("Error checking folder id: %v", err)
return true
}

Expand Down
5 changes: 2 additions & 3 deletions backend/db/vault.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"fmt"
"log"
"time"
"yeetfile/backend/utils"
"yeetfile/shared"
)

Expand Down Expand Up @@ -107,7 +106,7 @@ func GetVaultItems(
}

if err != nil {
utils.Logf("Error retrieving vault contents: %v", err)
log.Printf("Error retrieving vault contents: %v", err)
return nil, shared.FolderOwnershipInfo{}, err
}

Expand Down Expand Up @@ -306,7 +305,7 @@ func ShareFile(share shared.NewSharedItem, userID string) (string, error) {
func VaultItemIDExists(id string) bool {
rows, err := db.Query(`SELECT * FROM vault WHERE id=$1`, id)
if err != nil {
utils.Logf("Error checking vault item id: %v", err)
log.Printf("Error checking vault item id: %v", err)
return true
}

Expand Down
8 changes: 4 additions & 4 deletions backend/server/auth/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func SignupHandler(w http.ResponseWriter, req *http.Request) {
response = shared.SignupResponse{
Error: "Error creating account ID",
}
utils.Logf("Error: %v\n", err)
log.Printf("Error: %v\n", err)
} else {
response = shared.SignupResponse{
Identifier: id,
Expand Down Expand Up @@ -263,7 +263,7 @@ func VerifyAccountHandler(w http.ResponseWriter, req *http.Request) {
http.Error(w, "Unable to parse request", http.StatusBadRequest)
return
} else if utils.IsStructMissingAnyField(verify) {
utils.Log("Missing required fields for verification")
log.Println("Missing required fields for verification")
http.Error(w, "Unable to parse request", http.StatusBadRequest)
return
}
Expand Down Expand Up @@ -388,14 +388,14 @@ func PubKeyHandler(w http.ResponseWriter, req *http.Request, _ string) {
}

if err != nil || len(userID) == 0 {
utils.Logf("Error in user lookup for pub key: %v\n", err)
log.Printf("Error in user lookup for pub key: %v\n", err)
http.Error(w, "User not found", http.StatusNotFound)
return
}

pubKey, err := db.GetUserPubKey(userID)
if err != nil {
utils.Logf("Error fetching pub key: %v\n", err)
log.Printf("Error fetching pub key: %v\n", err)
http.Error(w, "User not found", http.StatusNotFound)
return
}
Expand Down
4 changes: 2 additions & 2 deletions backend/server/payments/btcpay/btcpay.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import (
"fmt"
"log"
"net/http"
"os"
"yeetfile/backend/config"
"yeetfile/backend/utils"
)

// IsValidRequest validates incoming webhook events from BTCPay Server
func IsValidRequest(w http.ResponseWriter, req *http.Request) ([]byte, bool) {
secret := os.Getenv("YEETFILE_BTCPAY_WEBHOOK_SECRET")
secret := config.YeetFileConfig.BTCPayBilling.WebhookSecret
sig := req.Header.Get("BTCPAY-SIG")
if len(sig) == 0 || len(secret) == 0 {
return nil, false
Expand Down
5 changes: 1 addition & 4 deletions backend/server/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package server
import (
"log"
"net/http"
"os"
"strings"
"yeetfile/shared"
"yeetfile/shared/endpoints"
Expand Down Expand Up @@ -63,9 +62,7 @@ func (r *router) AddRoutes(routes []RouteDef) {
func (r *router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
for el, handler := range r.routes {
if r.matchPath(el.Path, req.URL.Path) && el.Method == req.Method {
if os.Getenv("YEETFILE_DEBUG") == "1" {
log.Printf("%s %s\n", req.Method, req.URL)
}
log.Printf("%s %s\n", req.Method, req.URL)
handler(w, req)
return
}
Expand Down
4 changes: 4 additions & 0 deletions backend/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"log"
"net/http"
"os/signal"
"strings"
"syscall"
"yeetfile/backend/config"
"yeetfile/backend/server/auth"
Expand Down Expand Up @@ -172,6 +173,9 @@ func serve(r *router, host, port string) {
addr := fmt.Sprintf("%s:%s", host, port)

if len(config.TLSCert) > 0 && len(config.TLSKey) > 0 {
config.TLSKey = strings.ReplaceAll(config.TLSKey, "\\n", "\n")
config.TLSCert = strings.ReplaceAll(config.TLSCert, "\\n", "\n")

cert, err = tls.X509KeyPair(
[]byte(config.TLSCert),
[]byte(config.TLSKey))
Expand Down
1 change: 1 addition & 0 deletions backend/server/transfer/send/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func UserCanSend(size int64, req *http.Request) (bool, error) {
log.Printf("Error validating ability to upload: %v\n", err)
return false, err
} else if availableSend-usedSend < size {
log.Printf("[Send] Out of space: %d - %d > %d", availableSend, usedSend, size)
return false, OutOfSpaceError
}

Expand Down
4 changes: 2 additions & 2 deletions backend/server/transfer/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func UploadSingleChunk(upload FileUpload, b2Values db.B2Upload) (bool, error) {
upload.data)

if err != nil {
utils.Logf("Error uploading to B2: %v\n", err)
log.Printf("Error uploading to B2: %v\n", err)
return false, err
}

Expand Down Expand Up @@ -112,7 +112,7 @@ func UploadMultiChunk(upload FileUpload, b2Values db.B2Upload) (bool, error) {
upload.data)

if err != nil {
utils.Logf("Error: %v\n", err)
log.Printf("Error: %v\n", err)
return err
}

Expand Down
Loading

0 comments on commit a16992c

Please sign in to comment.