Skip to content

Commit

Permalink
Merge pull request #1 from fhir-fli/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
Dokotela authored Jul 24, 2024
2 parents 5ed2f80 + d000e2e commit 7951089
Show file tree
Hide file tree
Showing 58 changed files with 1,640,108 additions and 1 deletion.
24 changes: 24 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# flyctl launch added from .gitignore
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
**/*.exe
**/*.exe~
**/*.dll
**/*.so
**/*.dylib

# Test binary, built with `go test -c`
**/*.test

# Output of the go coverage tool, specifically when used with LiteIDE
**/*.out

# Dependency directories (remove the comment below to include it)
# vendor/

# Go workspace file
**/go.work
**/go.work.sum
fly.toml
18 changes: 18 additions & 0 deletions .github/workflows/fly-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# See https://fly.io/docs/app-guides/continuous-deployment-with-github-actions/

name: Fly Deploy
on:
push:
branches:
- main
jobs:
deploy:
name: Deploy app
runs-on: ubuntu-latest
concurrency: deploy-group # optional: ensure only one action runs at a time
steps:
- uses: actions/checkout@v4
- uses: superfly/flyctl-actions/setup-flyctl@master
- run: flyctl deploy --remote-only
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
38 changes: 38 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Use a Golang base image to build your custom PocketBase
FROM golang:1.21-alpine AS builder

# Set the working directory inside the container
WORKDIR /app

# Copy the Go modules manifests and download the dependencies
COPY go.mod go.sum ./
RUN go mod download

# Copy the rest of your PocketBase source code
COPY src/ .

# Build the custom PocketBase binary
RUN CGO_ENABLED=0 go build -o pocketfhir

# Use a minimal base image to package the custom PocketBase binary
FROM alpine:latest

# Set the working directory inside the container
WORKDIR /app

# Install necessary packages
RUN apk add --no-cache unzip openssh

# Copy the built binary from the builder stage
COPY --from=builder /app/pocketfhir /app/

# Set environment variables for directories (not secrets)
ENV PB_DATA_DIR /app/pb_data
ENV PB_PUBLIC_DIR /app/pb_public
ENV PB_HOOKS_DIR /app/pb_hooks

# Expose the necessary port
EXPOSE 8090

# Start the PocketBase server
CMD ["/app/pocketfhir", "serve", "--http=0.0.0.0:8090"]
73 changes: 72 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,73 @@
# pocket-fhir
A FHIR version of PocketBase

## All of this is based on the fabulous [PocketBase](https://pocketbase.io/), but designed for FHIR®

### Local Run
- Generate: ```$ ./generate_local.sh``` - this will also start the server the first time
- After that, you can just do: ```$ ./pocketfhir serve```

### Local-Docker Branch
- Regenerate: ```$ ./build/generate.sh``` - can still be run as the executable
- Generating will create two directories pb_data/ and pb_migrations/, which normally stay in the primary directory, but for this case, we copy them into the data/ directory
- You should then be able to run: ```$ docker-compose up --build```
- This will create a client, and while the command line says that it is serving at:
```
Server started at http://0.0.0.0:8090
pocketfhir-caddy | ├─ REST API: http://0.0.0.0:8090/api/
pocketfhir-caddy | └─ Admin UI: http://0.0.0.0:8090/_/
```
- It's actually located at ```https://localhost```
- Admin UI: [https://localhost/_/]
- If you want to upload some ValueSets and things to it using dart, in the dart directory, you can use the upload_all.dart file. You'll want to put in your username and password to make it work. Notice in this case, we also used the ```https://localhost``` for the PocketBase instance
- when you're done, use ```$ docker-compose down```

### GCP
- Based on [Rody Davis's](https://rodydavis.com/posts/pocketbase-cloudrun) version
- Go to GCP, make sure you have Cloud Storage
- Create a new bucket
- Give it a name, click continue
- Region - whatever your preference, continue
- Standard class, continue
- Control Access - whatever the default is, continue
- Data Protection - default
- Create
- run the generate script ```$ ./build/generate.sh```
- Copy the 2 folders (pb_data/ and pb_migrations/) to the storage bucket (you can just drag and drop)
- Complete the gcloud.sh file with appropriate values
- Run ```$ ./gcloud.sh``` - this should build and upload your docker container with Caddy to cloud run
- Go back into cloud run and select the new service
- Click Edit & Deploy New Revision
- Click Volume Tab
- Add Volume
- Volume Type -> Cloud Storage Bucket
- Volume name -> remote-storage (or whatever you want)
- Bucket -> the bucket you created that contains your folders
- Ensure you DO NOT check Read-only
- Click Container(s) Tab
- Partway down select Volume Mounts
- Name1 -> remote-storage (matches above)
- Mount path 1 -> /cloud/storage
- +Add Health Check
- Select health check type -> Liveness check
- Select probe type -> HTTP
- Path -> /api/health
- Initial delay -> 10
- Period -> 240
- Failure threshold -> 2
- Timeout -> 240
- Submit
- TODO

### Fly.io
- Generate locally: ```$ ./build/generate.sh```
- You need a Fly.io account (obviously) if you don't already have one
- Install on your local system
- macOS: brew install superfly/tap/flyctl
- Linux: curl -L https://fly.io/install.sh | sh
- CLI login: ```$ flyctl auth login```
- Make sure you have dotenv-cli installed: ```$ npm install -g dotenv-cli```
- Create app: ```$ flyctl apps create pocketfhir --org mayjuun```
- Create and mount the volume: ```$ flyctl volumes create pb_data --size=1 --app pocketfhir --region=atl```
- Set secrets: ```$ flyctl secrets set PB_ENCRYPTION_KEY=y5E69SptuHgUzspVNipzjl9ZmsKVPkIH --app pocketfhir```
- Deploy: ```$ flyctl deploy --app pocketfhir```
- May need to deploy a second time: ```$ flyctl deploy --app pocketfhir --wait-timeout 300```
49 changes: 49 additions & 0 deletions build/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Use a multi-stage build to compile PocketBase and set up Caddy
FROM golang:1.22.4-alpine AS builder

# Set the working directory
WORKDIR /app

# Copy the Go module files
COPY go.mod go.sum ./
RUN go mod download

# Copy the source code
COPY src/ ./

# Build the PocketBase server
RUN CGO_ENABLED=0 go build -o /app/pocketfhir

# Use a lightweight image for the final container
FROM caddy:2.6.2-alpine

# Create a non-root user
RUN addgroup -S caddy && adduser -S caddy -G caddy

# Set the working directory
WORKDIR /app

# Copy the PocketBase executable from the builder stage
COPY --from=builder /app/pocketfhir /app/

# Copy Caddy configuration file
COPY config/caddy/Caddyfile.prod /etc/caddy/Caddyfile

# Ensure pb_data, pb_public, and pb_hooks directories exist
RUN mkdir -p /cloud/storage/pb_data /cloud/storage/pb_public /cloud/storage/pb_hooks

# Copy entrypoint script
COPY build/entrypoint.sh /app/entrypoint.sh
RUN chmod +x /app/entrypoint.sh

# Change ownership of /app and /cloud/storage directories to the non-root user
RUN chown -R caddy:caddy /app /cloud/storage

# Expose the necessary port for Cloud Run
EXPOSE 8080

# Switch to the non-root user
USER caddy

# Command to run the entrypoint script
ENTRYPOINT ["/app/entrypoint.sh"]
18 changes: 18 additions & 0 deletions build/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/sh

# Use the PORT environment variable or default to 8090
PORT=${PORT:-8090}

# Start the PocketBase server
/app/pocketfhir serve --http=0.0.0.0:$PORT --dir=/cloud/storage/pb_data --publicDir=/cloud/storage/pb_public --hooksDir=/cloud/storage/pb_hooks &

# Wait for PocketBase to be ready
while ! nc -z 127.0.0.1 $PORT; do
echo "Waiting for PocketBase to be ready on port $PORT..."
sleep 2
done

echo "PocketBase is ready, starting Caddy..."

# Start the Caddy server
caddy run --config /etc/caddy/Caddyfile --adapter caddyfile
42 changes: 42 additions & 0 deletions build/generate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/bin/bash

# Navigate to the root directory of the project
cd "$(dirname "$0")/.."

# Clean up previous builds
rm -f pocketfhir

# Initialize Go modules in the root directory if go.mod does not exist
if [ ! -f go.mod ]; then
go mod init pocketfhir
fi

# Tidy up Go modules in the root directory
go mod tidy

# Build the PocketBase server and place the executable in the root directory
CGO_ENABLED=0 go build -o pocketfhir ./src

# Start the PocketBase server in the background
./pocketfhir serve &
PB_PID=$!

# Wait for the pb_migrations and pb_data directories to be generated
while [ ! -d "./pb_migrations" ] || [ ! -d "./pb_data" ]; do
echo "Waiting for pb_migrations and pb_data directories to be generated..."
sleep 2
done

# Stop the PocketBase server
kill $PB_PID

sleep 1

# Copy the generated directories to the data directory
cp -r ./pb_migrations ./data/pb_migrations
cp -r ./pb_data ./data/pb_data

rm -r ./pb_migrations
rm -r ./pb_data

echo "PocketFHIR build completed successfully."
23 changes: 23 additions & 0 deletions build/generate_local.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/bin/bash

# Navigate to the root directory of the project
cd "$(dirname "$0")/.."

# Clean up previous builds
rm -f pocketfhir

# Initialize Go modules in the root directory if go.mod does not exist
if [ ! -f go.mod ]; then
go mod init pocketfhir
fi

# Tidy up Go modules in the root directory
go mod tidy

# Build the PocketBase server and place the executable in the root directory
CGO_ENABLED=0 go build -o pocketfhir ./src

# Start the PocketBase server in the background
./pocketfhir serve

echo "PocketFHIR build completed successfully."
29 changes: 29 additions & 0 deletions build/selfsigned.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
-----BEGIN CERTIFICATE-----
MIIFCTCCAvGgAwIBAgIUF7sWRHuAqrSiFSSGbmajjNuUrDcwDQYJKoZIhvcNAQEL
BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI0MDcxMjIyMzQyNFoXDTI1MDcx
MjIyMzQyNFowFDESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEF
AAOCAg8AMIICCgKCAgEApE1kw1njEo5SNJ+pl7CljfaSpNOtz9qwZWyYhMJeXB7W
ersbiQesIpLJJcrl2bawGb27twm7O0wvNaaC8VkH/ezjqNnEjJGQapbPpy6MYAn4
71+kfiBzcNGyGVg2rRe2pdtgeQOH4JDcZguMGY1jT6k+5fm8KojhCuzPDwYxwFZc
kDhPU0DyhrUCOfGv1ENSXOm99IfIRva6rO71738VjrrnQvIOV+WpKbuIFgUjWTqp
A8tAPV3Sth1gZfAQtirGdFsOGs+84VhhrRe8RW8wBqadOxw9y3hlpiPKbd0kfpBa
X0D6Zy1tOpYEvXUrBBwNqhs4xmCnvFYlYgTiOd1Jr6CxV7IJ7wxtPJErbNDK+4/s
BcTh3nBVrK29i+pTzn8wVtkTYV2untKRG7uOlsWkO65+5BclgXTdPQdT02dHuK40
kSOt8Oe/DWBvCqj6srYaueczWU4KZ4wUE4f1G0IjXZiWUDmOvC720SebGQJc/hqw
GuPpfXZJ9IMI8GJh2FQWk/mMyvl7Rwbfeja1Jk26e6kJjwtMHnJ8xuJyDd8LPFDS
WOgXWv2/eCtnRk4P/6wyO4vYWKqZHFkg+eYX0qM4ajej0TXFAvg6rujCbGN3xWWS
i9yPlZCymXTtUIWSoLUiNf7tTMT1nEq0Np+oxU67V6VjbsSwjHoHgx3LIX2AjRcC
AwEAAaNTMFEwHQYDVR0OBBYEFCEH/jMv1M9HPb8PnNHB3p4HXms5MB8GA1UdIwQY
MBaAFCEH/jMv1M9HPb8PnNHB3p4HXms5MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
hvcNAQELBQADggIBAJ4ttyln7B8UFDRr4MQUmEo809da87eJC/lbR/WX0N4hphvk
nsMfUNuzipvfatzsQTh/u3r4/VERY4dk8U0CEZfRjliD76ly0lmwpNOwyJtayV0Z
OQMCM8p9D6bWHrt4KE72qCJE90U6MMkkl9iv1akGpqml7NxD1SqdegkQrQkcZNOO
yma/EMi66OEb1zf6D1omnYF2mN5JYJVsufo904xK0ucTzYIaEIyP8ZL2eXMptCCL
1voKSWZd+rAqYgEurmik4W/3KqAfEUQIhvI081PtlESpHplI7uimLLQrm8ceEbfW
FQNhmA0uHMGlRlNUrhYmVhhp8SjMVoIeQhp/Ok8vo0DQdeTcm8hNvtPRuzeXAA5G
1jqXKtTqsuGdfSpvKGlXxdooCIKLplK7PTUwtN5/nci2mcMQaGCpjepvm+Ca0neP
FXj++3G/g8PzrXSw89C6J+D1hXDYtMZJBItWPkdYdaeL6X0/J5EvIlXs9K14J+3/
a/8JEkLnBeRCmI1rFGpO4B8tH7kCGivG7pTG0DTApjnABSefoQzsot4KrrFRaeKQ
GPIvXI4RkJNq6+Yez0pJGUQ3ghlSXHsaW04Vf+m2ll52MFgNZ9srOK76NTIMZuBq
PWEkAV7YumS6lek5u8Hu/mt0wapx2KvOmpBOJt+MiB8/1GkUicHHaD7fGpGY
-----END CERTIFICATE-----
52 changes: 52 additions & 0 deletions build/selfsigned.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
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
4RsoVjbAiNu+sEbAXskQ9tbizjqP
-----END PRIVATE KEY-----
3 changes: 3 additions & 0 deletions config/.env.flyio
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# ./config/.env.flyio
PB_ENCRYPTION_KEY=y5E69SptuHgUzspVNipzjl9ZmsKVPkIH
AUTO_HTTPS=on
3 changes: 3 additions & 0 deletions config/.env.local
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
PB_ENCRYPTION_KEY=y5E69SptuHgUzspVNipzjl9ZmsKVPkIH
AUTO_HTTPS=local_certs
TLS_CERT=tls /etc/caddy/selfsigned.crt /etc/caddy/selfsigned.key
2 changes: 2 additions & 0 deletions config/.env.prod
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
PB_ENCRYPTION_KEY=y5E69SptuHgUzspVNipzjl9ZmsKVPkIH
AUTO_HTTPS=on
Loading

0 comments on commit 7951089

Please sign in to comment.