A git hook-based Phoenix deploy
This is what I did. Suggestions or improvements are welcome. Here I’m assuming the app is called my_app
and it will run as app_user
.
Create a bare git repository
ssh app_user@my_server
mkdir repo
cd repo
git init --bare
Create a post-receive hook /home/app_user/repo/hooks/post-receive
with something like this
#!/bin/bash
echo "Updating code.."
git --work-tree=/home/app_user/app --git-dir=/home/app_user/repo checkout -f
cd /home/app_user/app
export SECRET_KEY_BASE="[whatever it is]"
echo "Updating dependencies..."
mix deps.get --only prod
echo "Compiling app..."
MIX_ENV=prod mix compile
echo "Updating JS dependencies.."
npm install --prefix ./assets
echo "Compiling assets..."
npm run deploy --prefix ./assets
mix phx.digest
echo "Building app..."
MIX_ENV=prod mix release --overwrite
echo "Restarting server..."
sudo systemctl restart my_app
echo "Done!"
Now make the bare repository a remote
git remote add production app_user@my_server:repo
You can now deploy with
git push production master
The service is handled by systemd. This is how the service is defined (/etc/systemd/system/my_app.service
):
[Unit]
Description=my_app service
After=local-fs.target network.target
[Service]
Type=simple
User=app_user
Group=app_user
WorkingDirectory=/home/my_app/app/_build/prod/rel/my_app
ExecStart=/home/my_app/app/_build/prod/rel/my_app/bin/my_app start
ExecStop=/home/my_app/app/_build/prod/rel/my_app/bin/my_app stop
Environment=LANG=en_US.utf8
Environment=MIX_ENV=prod
Environment=PORT=4000
LimitNOFILE=65535
UMask=0027
SyslogIdentifier=my_app
Restart=always
[Install]
WantedBy=multi-user.target