Skip to content

Installation Guide

This guide walks you through the process of installing and configuring Arrow on your infrastructure.

Before installing Arrow, ensure you have the following:

ComponentRequirement
Node.jsv18.0 or higher
Gov1.22 or higher
PNPMv8.0 or higher
Memory4GB RAM minimum (8GB recommended)
Storage20GB available disk space
OSLinux (Ubuntu 22.04+ recommended), macOS, or Windows

To enable all Arrow features, you’ll need accounts with the following services:

ServicePurposeRequired
NetbirdVPN orchestrationYes
ZitadelAuthenticationYes
Backblaze B2File storage (S3-compatible)Yes
EasyPostShipment trackingOptional
HelpScoutSupport integrationOptional
BluesGPS trackingOptional
MapboxGeocoding/mapsOptional
CloudflareDNS/CDN/TurnstileOptional
QuickBooksBilling integrationOptional
ResendEmail notificationsOptional
  • Domain Name: A domain for your Arrow instance (e.g., arrow.yourcompany.com)
  • SSL Certificate: Let’s Encrypt (automated) or your own certificate
  • Network: Outbound HTTPS access for integrations
  • Firewall: Ports 80, 443 open for web traffic
Terminal window
git clone https://github.com/your-org/arrow.git
cd arrow
Terminal window
cd backend
Terminal window
cp .env.example .env

Edit the .env file with your configuration. See Environment Variables for a complete reference.

At minimum, configure these required variables:

Terminal window
# Storage Configuration
B2_BUCKET=your-bucket-name
B2_REGION=us-east-1
B2_ENDPOINT=https://s3.us-east-1.backblazeb2.com
B2_KEY_ID=your-key-id
B2_APP_KEY=your-app-key
# Dashboard URL
DASHBOARD_URL=https://arrow.yourcompany.com

Arrow uses PocketBase which handles migrations automatically on first run. The database will be created in the pb_data directory.

For development:

Terminal window
go run main.go serve

For production, build and run the binary:

Terminal window
go build -o arrow-backend main.go
./arrow-backend serve

Access the PocketBase admin interface:

https://your-domain.com/_/

If the admin interface loads successfully, your backend is running correctly.

Terminal window
cd ../frontend
Terminal window
pnpm install

3. Configure Frontend Environment Variables

Section titled “3. Configure Frontend Environment Variables”

Create a .env file in the frontend directory:

Terminal window
VITE_API_URL=http://localhost:8090
VITE_VPN_BASE_DOMAIN=arrowvpn.io
Terminal window
pnpm dev

The frontend will be available at http://localhost:5173

Terminal window
pnpm build

The production build will be output to the dist directory. Deploy this to your web server or CDN.

After installation, complete these configuration steps:

Navigate to your Arrow URL and you’ll be presented with the login screen.

For the first run, create an admin account through the PocketBase admin interface at /_/:

  1. Navigate to /_/
  2. Create the admin account
  3. Log in to the Arrow console with your new credentials

In the Arrow console:

  1. Go to Settings > Organization
  2. Enter your organization name and details
  3. Configure default settings for device requests

Configure Zitadel for authentication:

  1. Create a Zitadel project and application
  2. Note the client ID and client secret
  3. Configure the allowed redirect URIs
  4. Add Zitadel credentials to your backend environment variables

Set up Netbird integration:

  1. Create a Netbird account and setup key
  2. Configure the Netbird management URL
  3. Add Netbird credentials to your backend environment variables
  4. Test VPN connectivity

6. Set Up EasyPost for Shipment Tracking (Optional)

Section titled “6. Set Up EasyPost for Shipment Tracking (Optional)”

If using shipment tracking:

  1. Create an EasyPost account
  2. Generate API keys (test and production)
  3. Configure webhook endpoints
  4. Add EasyPost credentials to your backend environment variables

Use this checklist to verify your installation is complete:

  • Backend Running: PocketBase admin interface loads at /_/
  • Frontend Accessible: Console loads at your domain
  • Admin Login: Can log in with admin credentials
  • Database Created: pb_data directory exists with database file
  • Zitadel Connected: Authentication works through Zitadel (if configured)
  • Netbird Connected: VPN management accessible (if configured)
  • Storage Working: File uploads work correctly
  • Email Sending: Test email notifications (if Resend configured)

For production deployments, consider:

Use a process manager like systemd:

[Unit]
Description=Arrow Backend
After=network.target
[Service]
Type=simple
User=arrow
WorkingDirectory=/opt/arrow/backend
ExecStart=/opt/arrow/backend/arrow-backend serve
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target

Configure nginx or Caddy as a reverse proxy:

server {
listen 443 ssl http2;
server_name arrow.yourcompany.com;
ssl_certificate /etc/letsencrypt/live/arrow.yourcompany.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/arrow.yourcompany.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8090;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}

Set up automated backups of the pb_data directory which contains the SQLite database and uploaded files.

IssueSolution
Port 8090 in useChange the port with --http=0.0.0.0:8091 flag
Database lockedEnsure only one instance is running
CORS errorsVerify DASHBOARD_URL matches your frontend URL
SSL certificate errorsCheck Let’s Encrypt configuration or certificate paths
Build failuresEnsure Go and Node.js versions meet requirements

For more troubleshooting help, see the Troubleshooting guide.