Gearmand
Overview
Gearman is a mature, language-agnostic job server. An application hands a unit of work to the server, which dispatches it to whichever worker process is free and returns the result to the caller. Workers can be written in a different language from the client, can run on a different machine, and can be added or removed while the system is running.
This guide covers deploying and using Gearman Job Server on Ubuntu 24.04 on Azure using SecureAnyCloud Azure Marketplace images. The image installs gearman-job-server 1.1.20 (gearmand) and the gearman / gearadmin command line tools from the signed Ubuntu 24.04 archive (GPG-verified by apt). The job server keeps receiving Ubuntu security updates on your running VM. The persistent background-job queue is stored on-box in SQLite, and a read-only status console is served over HTTPS.
The problem this image solves. Upstream Gearman has no authentication and no access control of any kind. Every client that can open a TCP connection to port 4730 can submit jobs, read and drain the queue, and register itself as a worker for any function, including functions your own application defines.
Stock packages bind that port to every interface, which turns an internet-reachable Gearman server into an open remote-execution surface.
Closed by default. This image inverts that dangerous default:
- The job protocol is bound to 127.0.0.1 only (loopback). Nothing outside the instance can reach port 4730 until you deliberately change it.
- The recommended Network Security Group opens SSH and the status console only, never port 4730.
- Two independent start guards enforce the binding. The job server does not start until first boot has provisioned this instance (
ConditionPathExistson a per-VM bootstrap marker). A start-time guard refuses to start the service if the listen address is a world-open value such as0.0.0.0. - The build proves that the job protocol refuses a connection on the instance's own routable address, and that nothing unexpected is listening on a non-loopback address.
Secure by default, with no shared credential. The shipped image contains no valid status-console password. On the first boot of every VM, a one-shot service mints a 28-character password unique to that instance and hashes it with bcrypt. It also issues a per-instance TLS certificate and writes the details to /root/gearmand-credentials.txt (mode 0600, root only).
What you get:
gearman-job-server 1.1.20(gearmand) plusgearman-tools(thegearmanclient/worker CLI andgearadmin), installed from the signed Ubuntu archive and managed by systemd.- The job protocol bound to 127.0.0.1:4730 only, with a persistent SQLite background-job queue at
/var/lib/gearman/gearmand-queue.db. - A read-only HTTPS status console on port 443 (
/status) behind bcrypt basic auth with a per-instance password, plus an unauthenticated/healthzendpoint for load balancer and monitoring probes. - A per-instance TLS certificate and status-console password minted on first boot and recorded in
/root/gearmand-credentials.txt(0600). - Client libraries for PHP, Perl, Python, Ruby, Java, Go, C and Node.js, so existing workers connect without code changes.
Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM). Gearman is extremely light. Scale by running more worker processes rather than resizing the job server.
Deploy from the Azure Portal
Search for Gearman Job Server in Marketplace, select the SecureAnyCloud publisher, and choose Create. Configure the Network Security Group to allow TCP 22 for administration and TCP 443 for the status console, both restricted to trusted source addresses. Do not open TCP 4730. The job protocol is loopback-only by design.
Deploy from the Azure CLI
Run these commands from a workstation where you are signed in to the Azure CLI:
RG="gearmand-prod"; LOCATION="eastus"; VM_NAME="gearmand-01" IMAGE_URN="sac1647283583153:gearmand:default:latest" SSH_KEY="$(cat ~/.ssh/id_rsa.pub)" az group create --name "$RG" --location "$LOCATION"
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:gearmand:default:latest
az vm create \
--resource-group "$RG" --name "$VM_NAME" \
--image "$IMAGE_URN" \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values "$SSH_KEY" \
--public-ip-sku Standard
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 22 --priority 1001
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 443 --priority 1002Deploy inside your own virtual network, and restrict the Network Security Group to trusted networks.
First boot and reading your credentials
On first boot, the image generates this instance's status-console password and writes the bcrypt htpasswd entry. It issues a per-instance TLS certificate whose subject alternative name carries this VM's address, seeds the status snapshot, and writes /root/gearmand-credentials.txt. This completes within a minute.
Connect over SSH as azureuser and read the details:
sudo cat /root/gearmand-credentials.txtThe file records GEARMAN_STATUS_USER, GEARMAN_STATUS_PASSWORD and the console URLs. The password is unique to this instance and is never shared with any other VM.
Confirm the service is running and bound to loopback
Both gearman-job-server.service and nginx.service are active. The job protocol is bound to 127.0.0.1:4730 only. The ss command shows it on loopback, while only SSH (22), HTTP (80) and HTTPS (443) are reachable off-box.
systemctl is-active gearman-job-server.service nginx.service ss -Hltn | awk '{print $4}' | sort -uExpected output: the job protocol appears as 127.0.0.1:4730, never 0.0.0.0:4730.
active active 0.0.0.0:22 0.0.0.0:443 0.0.0.0:80 127.0.0.1:4730 [::]:22 [::]:443 [::]:80The shipped exposure check enumerates every listening socket. It fails closed on any unexpected non-loopback listener:
sudo /usr/local/sbin/gearman-exposure-check.sh '22 80 443'Submit a job and see the result
This is the core of the product. A worker registers for a named function, a client submits a job for that function, and the result is returned through the job server.
Register a worker for a reverse function backed by the rev command, submit one job, and read the reversed result back. gearadmin --status then reflects the registered function, and gearadmin --workers shows the connected worker.
# Register a worker for the 'reverse' function (backed by /usr/bin/rev), in the background gearman -h 127.0.0.1 -p 4730 -w -f reverse -- /usr/bin/rev & WORKER_PID=$! sleep 2
# gearadmin reflects the registered function: name queued running workers echo "== gearadmin --status ==" gearadmin --status | grep '^reverse'
# Submit a job from a client and read the result returned through the job server echo "== submit a job ==" printf 'Hello Gearman' | gearman -h 127.0.0.1 -p 4730 -f reverse echo
# gearadmin shows the connected worker registered for 'reverse' echo "== gearadmin --workers ==" gearadmin --workers | grep reverse kill "$WORKER_PID" 2>/dev/nullExpected output: the client sends Hello Gearman, the worker reverses it, and the result namraeG olleH returns through the job server.
== gearadmin --status == reverse 0 0 1 == submit a job == namraeG olleH == gearadmin --workers == 37 127.0.0.1 - : reverseBackground jobs and the persistent queue
Background jobs are accepted immediately and queued for a worker to pick up later. They are written to an on-box persistent SQLite queue, so work accepted before a restart is replayed after it rather than lost.
Submit a background job, check that it is in the queue and persisted to SQLite, then drain it with a worker.
# Submit a BACKGROUND job (returns immediately with a job handle) printf 'process-me' | gearman -h 127.0.0.1 -p 4730 -b -f demo_bg sleep 1
# The job is queued (queued count is 1) ...
echo "== queued ==" gearadmin --status | grep '^demo_bg'
# ... and persisted to the on-box SQLite queue database
echo "== persisted to SQLite =="
sudo sqlite3 -readonly /var/lib/gearman/gearmand-queue.db \
"select function_name, length(data) as bytes from gearman_queue where function_name='demo_bg';"
# Drain it with a one-shot worker
echo "== drain ==" gearman -h 127.0.0.1 -p 4730 -w -c 1 -f demo_bg -- /bin/cat >/dev/null && echo "background job drained by a worker"The read-only HTTPS status console
A read-only status console is served over HTTPS on port 443. It shows live queue depth, registered functions, connected workers and the running version. These are the numbers you need for capacity planning and alerting. The console never exposes the job protocol itself.
The console is protected by HTTP basic authentication, with a password generated for this instance on first boot. A separate unauthenticated /healthz endpoint is provided for load balancer and monitoring probes. Because the console serves the per-instance self-signed certificate, the commands use curl with -k.
STATUS_USER=$(sudo grep '^GEARMAN_STATUS_USER=' /root/gearmand-credentials.txt | cut -d= -f2-)
STATUS_PASS=$(sudo grep '^GEARMAN_STATUS_PASSWORD=' /root/gearmand-credentials.txt | cut -d= -f2-)
echo -n 'healthz (unauthenticated): HTTP '; curl -sk -o /dev/null -w '%{http_code}\n' https://127.0.0.1/healthz
echo -n '/status without a password: HTTP '; curl -sk -o /dev/null -w '%{http_code}\n' https://127.0.0.1/status
echo '--- /status with this instance credentials ---' curl -sk -u "$STATUS_USER:$STATUS_PASS" https://127.0.0.1/status | head -14Expected output: /healthz returns 200 unauthenticated. /status returns 401 without the password and the live snapshot with it.
healthz (unauthenticated): HTTP 200 /status without a password: HTTP 401 --- /status with this instance credentials --- sac Gearman Job Server - status generated : ... host : ... listening : 127.0.0.1:4730Verify the security posture
The job protocol is loopback-only. You can prove it: the port refuses a connection on this VM's own routable (private NIC) address, because only 127.0.0.1 is bound.
The start-time guard also refuses to start the service against a world-open listen address such as 0.0.0.0, the upstream default.
# The routable NIC address of this VM
PRIV=$(hostname -I | awk '{print $1}')
echo "routable address: $PRIV"
# A connection to 4730 there MUST be refused (the port is loopback-only) if timeout 5 bash -c "exec 3<>/dev/tcp/$PRIV/4730" 2>/dev/null; then
echo "UNEXPECTED: 4730 was reachable on $PRIV" else
echo "OK: 4730 refused on the routable address $PRIV (loopback only)" fi
# The start-time guard refuses a world-open listen address (the upstream default) GEARMAND_LISTEN=0.0.0.0 /usr/local/sbin/gearman-listen-guard.sh \
|| echo "OK: the start-time guard refuses GEARMAND_LISTEN=0.0.0.0"
# The credentials file is root-readable only
sudo stat -c '%n %a %U:%G' /root/gearmand-credentials.txtExposing the job server to your own private subnet
Gearman has no native authentication, so exposing port 4730 is a deliberate decision, not a default. To let workers on other hosts in your own private subnet reach the job server, make a two-part change. Scope it tightly to your own network, never to the internet.
First, change the listen address in /etc/default/gearman-job-server from loopback to this VM's private address. Use a specific private IP, never 0.0.0.0, because the start-time guard refuses a world-open value:
# /etc/default/gearman-job-server (excerpt)
# Set to THIS VM's private NIC address, e.g. 10.0.0.14 — never 0.0.0.0. GEARMAND_LISTEN=10.0.0.14Then restart the service and add one Network Security Group rule that allows TCP 4730 only from your own VNet/subnet CIDR:
sudo systemctl restart gearman-job-server.service az network nsg rule create --resource-group "$RG" --nsg-name "$NSG" \
--name AllowGearmanFromSubnet --priority 1004 \
--access Allow --protocol Tcp --direction Inbound \
--destination-port-ranges 4730 --source-address-prefixes "<your-vnet-cidr>"Because Gearman has no authentication, anyone who can reach port 4730 can submit and consume jobs. Keep the source scoped to your own private CIDR, and never add a rule for 4730 from 0.0.0.0/0 or Internet.
For stronger isolation, front the job server with mutual TLS through a proxy such as stunnel, or place workers and the job server in a dedicated private subnet.
Monitoring
Point your load balancer or monitoring system at the unauthenticated health endpoint. Read live queue metrics from the authenticated status console or with gearadmin:
# Liveness for a load balancer or uptime monitor (no credential needed)
curl -sk -o /dev/null -w 'healthz: HTTP %{http_code}\n' https://127.0.0.1/healthz
# Live queue depth and worker counts (function queued running workers) gearadmin --statusWriting your own worker
A worker connects to the job server, registers for one or more function names, and executes jobs. The CLI worker used above wraps any command. In production, you use a client library. For example, in Python with python-gearman:
import gearman class Worker(gearman.GearmanWorker): pass worker = Worker(['127.0.0.1:4730']) def reverse(worker, job): return job.data[::-1] worker.register_task('reverse', reverse) worker.work()Client libraries exist for PHP, Perl, Python, Ruby, Java, Go, C and Node.js. Point each worker at 127.0.0.1:4730 on the job server host. For workers on other hosts in your subnet, use the private address you configured in Step 9.
Troubleshooting
- First boot has not finished. If
/root/gearmand-credentials.txtstill shows only comment lines, first boot has not completed. Check it withsystemctl status gearmand-firstboot.service. - The service will not start. The start-time guard refuses a world-open listen address. Check that
GEARMAND_LISTENin/etc/default/gearman-job-serveris127.0.0.1or a specific private address. Then checkjournalctl -u gearman-job-server.service. - Workers on other hosts cannot connect. Confirm that you changed
GEARMAND_LISTENto the VM's private address (Step 9), restarted the service, and added the scoped NSG rule for TCP 4730. - The status console returns 401. Use the exact
GEARMAN_STATUS_USERandGEARMAN_STATUS_PASSWORDvalues from/root/gearmand-credentials.txt.
Support
SecureAnyCloud provides 24/7 technical support for this product by email at sales@secureanycloud.com and through live chat. Support covers deployment, exposing the job server to your own subnet safely, worker and client connectivity across languages, persistent queue behaviour and sizing, status console access, TLS certificate replacement, monitoring, Network Security Group scoping, and version and patch guidance.
Gearman is distributed under the BSD 3-Clause License. All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.
Deploy on Azure
Launch Gearman Job Server 1.1.20 on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need help?
Our support team is available 24/7.
sales@secureanycloud.com
Overview
Gearman is a mature, language-agnostic job server. Your application hands a unit of work to the job server, the job server hands it to whichever worker process is free, and the result comes back to the caller. Workers can be written in a different language from the client, can live on a different machine, and can be added or removed while the system is running.
This is a headless product. There is no web application to log in to. You administer it over SSH, and a read-only HTTPS status console shows you queue depth and worker counts.
Gearman has no authentication and no access control. Any client that can open a TCP connection to port 4730 can submit jobs, read and drain the queue, and register itself as a worker for any function, including functions your own application defines. An internet-reachable Gearman job server is an open remote execution surface.
This image ships it closed. The job protocol is bound to 127.0.0.1 only. The recommended security group never opens 4730. Letting workers on other hosts reach the job server is a deliberate, documented two-step change, covered in the exposure section near the end of this guide.
What you get:
- Gearman job server
gearmand1.1.20 and thegearman/gearadmincommand line tools, installed from the signed distribution archive (BSD 3-Clause License), so the instance keeps receiving distribution security updates. - The job protocol bound to
127.0.0.1:4730through/etc/default/gearman-job-server, managed by systemd. - A persistent SQLite background job queue at
/var/lib/gearman/gearmand-queue.dbon its own dedicated, independently resizable block storage volume. - A read-only HTTPS status console on port 443, protected by HTTP basic authentication. The password is generated uniquely for your instance on first boot and stored bcrypt-hashed.
- An unauthenticated
/healthzendpoint for load balancer and monitoring probes. gearmand-firstboot.service, which mints the console password, issues a per-instance TLS certificate and writes/root/gearmand-credentials.txt(mode 0600 root:root)./usr/local/sbin/gearman-exposure-check.sh, a fail-closed audit of every listening socket on the instance.- 24/7 SecureAnyCloud support.
Prerequisites
- An AWS account, an EC2 key pair, and a VPC subnet.
- A security group that allows inbound TCP 22 (SSH) and TCP 443 (status console) from your trusted CIDR.
- An instance type of m5.large, which is a comfortable default.
Do not open TCP 4730 to the internet.
Connecting to your instance
Connect over SSH as the default login user for the operating system variant you launched. This listing currently ships one variant, Ubuntu 24.04 LTS, and its SSH login user is ubuntu.
ssh ubuntu@<public-ip>Launch from AWS Marketplace
Subscribe to the SecureAnyCloud Gearman Job Server listing and launch an instance. Pick m5.large and choose your VPC and subnet. Attach a security group that allows inbound TCP 22 and TCP 443 from your trusted CIDR only.
The instance boots with two volumes: the operating system disk, and a dedicated volume mounted at /var/lib/gearman that holds the persistent job queue.
SSH in
Connect to the instance:
ssh ubuntu@<public-ip>The login banner prints the status console URL and the commands you need most.
Confirm the services are running
Two services make up the appliance: the job server itself and the nginx front end that serves the status console.
sudo systemctl is-active gearman-job-server nginxactive activeConfirm the job protocol is loopback only
This is the most important check on the instance. gearmand must listen on 127.0.0.1 and nowhere else.
BIND="$(sudo ss -Hltn | awk '{print $4}' | grep ':4730$')" echo "Gearman job protocol is listening on: ${BIND}" case "${BIND}" in 127.0.0.1:4730) echo "CONFIRMED: loopback only - not reachable from any other host" ;; *) echo "This job server is NOT loopback bound; review /etc/default/gearman-job-server"; exit 1 ;; esacGearman job protocol is listening on: 127.0.0.1:4730 CONFIRMED: loopback only - not reachable from any other hostThe shipped configuration file records the same setting, along with the procedure for widening access safely:
sudo grep -E '^GEARMAND_' /etc/default/gearman-job-serverGEARMAND_LISTEN=127.0.0.1 GEARMAND_PORT=4730 GEARMAND_QUEUE_DB=/var/lib/gearman/gearmand-queue.db GEARMAND_EXTRA_OPTS=Audit every listening socket
The image ships a fail-closed exposure audit. It lists every socket bound to a non-loopback address. It exits non-zero if anything outside the allow list appears, or if the job protocol has been bound off loopback. The same check runs during the build, before the image is captured.
sudo /usr/local/sbin/gearman-exposure-check.sh "22 80 443"--- non-loopback TCP listeners --- tcp 0.0.0.0:443 tcp 0.0.0.0:22 tcp 0.0.0.0:80 tcp [::]:443 tcp [::]:22 tcp [::]:80 --- non-loopback UDP listeners --- udp 172.31.93.204%ens5:68 --- gearman job protocol binding --- 127.0.0.1:4730 exposure check clean: only 22 80 443 (tcp) are non-loopbackOnly SSH and the status console are reachable from the network. The job protocol is not.
Read your per-instance credentials
First boot writes a root-only credentials file. It holds the status console user, the password generated for this instance, and the console URLs. Nothing in it is shared with any other instance.
The command below prints the key names only, never the values. It is safe to run in a shared terminal or paste into a ticket.
sudo grep -oE '^[A-Z_]+=' /root/gearmand-credentials.txtGEARMAN_STATUS_USER= GEARMAN_STATUS_PASSWORD= <set-at-first-boot>= GEARMAN_HEALTH_URL= GEARMAN_JOB_SERVER=To read the whole file, including the password, run sudo cat /root/gearmand-credentials.txt on your own instance.
Check that the status console requires authentication
The console is served over HTTPS. Without credentials it returns 401, and with them it returns 200. The block below reads the password into a shell variable rather than printing it.
sudo bash -c ' U=$(grep -m1 "^GEARMAN_STATUS_USER=" /root/gearmand-credentials.txt | cut -d= -f2-) P=$(grep -m1 "^GEARMAN_STATUS_PASSWORD=" /root/gearmand-credentials.txt | cut -d= -f2-) UNAUTH=$(curl -sk -o /dev/null -w "%{http_code}" https://127.0.0.1/status) AUTH=$(curl -sk -o /dev/null -w "%{http_code}" -u "$U:$P" https://127.0.0.1/status) echo "status console, no credentials : HTTP ${UNAUTH}" echo "status console, with credentials : HTTP ${AUTH}" [ "${UNAUTH}" = 401 ] && [ "${AUTH}" = 200 ] || { echo "the status console did not behave as documented"; exit 1; } 'status console, no credentials : HTTP 401 status console, with credentials : HTTP 200The certificate is a per-instance self-signed certificate issued at first boot, with your instance address in its subject alternative name. The commands use -k because the certificate is self-signed. To replace it with your own, see the certificate section below.
Read the status console
The console shows the server version and process id, the queue (one row per registered function, with queued, running and worker counts) and the connected workers. It is strictly read-only, and it never proxies the job protocol.
sudo bash -c ' U=$(grep -m1 "^GEARMAN_STATUS_USER=" /root/gearmand-credentials.txt | cut -d= -f2-) P=$(grep -m1 "^GEARMAN_STATUS_PASSWORD=" /root/gearmand-credentials.txt | cut -d= -f2-) curl -sk -u "$U:$P" https://127.0.0.1/status'sac Gearman Job Server - status generated : 2026-07-26T08:39:13Z host : ip-172-31-93-204 listening : 127.0.0.1:4730 == server == version : 1.1.20+ds pid : 7458 == queue (function queued running workers) == . == workers == 37 127.0.0.1 - : .From your own workstation, browse to the GEARMAN_STATUS_URL value in the credentials file. Sign in with the status user and the generated password.
Use the unauthenticated health endpoint
Load balancer and monitoring probes need a target that does not require a credential. /healthz is a static 200 on both port 80 and port 443. It exposes nothing about the queue.
curl -s -o /dev/null -w 'health endpoint: HTTP %{http_code}\n' http://127.0.0.1/healthzhealth endpoint: HTTP 200Submit your first job
A Gearman round trip needs two halves. A worker registers a function name and does the work. A client submits a job for that function name and waits for the result.
The block below registers a worker for a function called reverse that runs the rev command, submits one job to it, and asserts that the result came back correctly. The -c 1 option makes the worker exit after a single job, so the example is self-contained.
timeout 30 gearman -h 127.0.0.1 -p 4730 -w -c 1 -f reverse -- rev >/dev/null 2>&1 & sleep 2 RESULT="$(printf 'gearman on sac' | timeout 30 gearman -h 127.0.0.1 -p 4730 -f reverse)" wait echo "worker returned: ${RESULT}" [ "${RESULT}" = "gmiduolc no namraeg" ] || { echo "the round trip did not return the reversed payload"; exit 1; }worker returned: gmiduolc no namraegThe payload went from the client, through the job server, into the worker's standard input. The worker's standard output came back as the job result.
Run background jobs with the persistent queue
Background jobs are the reason most people run Gearman. The client submits and returns immediately, and a worker picks the job up whenever it is free. This image writes those jobs to a SQLite queue on the dedicated volume, so a job accepted before a restart is still there afterwards.
The block below submits a background job and proves that it is both queued in memory and persisted to disk. It then starts a worker to drain the job and proves that the queue is empty again.
printf 'nightly-report' | timeout 20 gearman -h 127.0.0.1 -p 4730 -b -f build_report sleep 2 gearadmin --status | grep '^build_report' || { echo "the background job was not queued"; exit 1; }
sudo sqlite3 -readonly /var/lib/gearman/gearmand-queue.db "select function_name, unique_key from gearman_queue;" timeout 30 gearman -h 127.0.0.1 -p 4730 -w -c 1 -f build_report -- cat >/dev/null 2>&1 sleep 1 echo "after the worker ran:" gearadmin --status | grep '^build_report' REMAIN="$(sudo sqlite3 -readonly /var/lib/gearman/gearmand-queue.db 'select count(*) from gearman_queue;')" echo "rows still persisted: ${REMAIN}" [ "${REMAIN}" = "0" ] || { echo "the queue did not drain"; exit 1; }build_report 1 0 0 build_report|7aa82032-88cd-11f1-8d4f-12d811d5a21d after the worker ran: build_report 0 0 0 rows still persisted: 0The four columns from gearadmin --status are function name, queued, running and connected workers. The job appeared as one queued item and one row in the SQLite queue. Both cleared once a worker had run it.
Inspect the queue
gearadmin is the administration client. It talks to the job server over the same loopback socket. To see the queue, run:
gearadmin --statusbuild_report 0 0 0 .Other useful subcommands, all safe to run on a live server:
gearadmin --server-version gearadmin --getpid gearadmin --workers1.1.20+ds 7458 37 127.0.0.1 - : .Review the dedicated queue volume
The persistent queue lives on its own block storage volume, not on the operating system disk. You can resize it independently as your queue depth grows.
findmnt -no SOURCE,TARGET,FSTYPE,SIZE /var/lib/gearman df -h /var/lib/gearman | tail -1/dev/nvme1n1 /var/lib/gearman ext4 19.5G /dev/nvme1n1 20G 36K 19G 1% /var/lib/gearmanThe mount is recorded in /etc/fstab by filesystem UUID, so it reattaches on every boot. To grow it, expand the EBS volume in the AWS console, and then run sudo resize2fs /dev/nvme1n1.
Check the versions
Print the installed versions:
/usr/sbin/gearmand -V dpkg-query -W -f='${Package} ${Version}\n' gearman-job-server gearman-toolsgearmand 1.1.20+ds - https://github.com/gearman/gearmand/issues gearman-job-server 1.1.20+ds-1.2build4 gearman-tools 1.1.20+ds-1.2build4Exposing the job server to your own private subnet
Everything above ran on the instance itself, because that is the only place the job protocol is reachable from. If your workers run on other hosts, you can widen access, but do it deliberately.
Never open TCP 4730 to 0.0.0.0/0. There is no authentication behind it. A client that reaches it can register itself as a worker for one of your function names and receive your jobs, or drain your queue.
The safe pattern is two changes, and you must make both.
1. Change the listen address on the instance. Edit /etc/default/gearman-job-server and set GEARMAND_LISTEN to the instance's private address (or 0.0.0.0 if you have several interfaces). Then restart the service:
sudo sed -i 's/^GEARMAND_LISTEN=.*/GEARMAND_LISTEN=0.0.0.0/' /etc/default/gearman-job-server
sudo systemctl restart gearman-job-server
sudo ss -Hltn | awk '{print $4}' | grep ':4730$'2. Add one security group rule scoped to your own network. In the AWS console or with the CLI, allow TCP 4730 from your VPC or subnet CIDR and nothing wider:
aws ec2 authorize-security-group-ingress \
--group-id sg-your-security-group \
--protocol tcp --port 4730 \
--cidr 10.0.0.0/16Re-run the exposure audit afterwards with 4730 added to the allow list. This gives you a record of exactly what is reachable:
sudo /usr/local/sbin/gearman-exposure-check.sh "22 80 443 4730"For defence in depth, keep the job server on loopback and give each worker host an SSH tunnel to it instead. That keeps the protocol entirely off the network:
ssh -N -L 4730:127.0.0.1:4730 ubuntu@your-job-serverConnecting your own workers and clients
Gearman client libraries exist for most languages, and they all speak the same wire protocol as the gearman command line tool used above. Point them at the job server address and the function names you register.
Install these common libraries from your own language's package manager on your own application hosts, not on this instance:
- PHP: the gearman PECL extension.
- Python: python-gearman or gearman3.
- Perl: Gearman::Client and Gearman::Worker.
- Ruby: gearman-ruby.
- Java: java-gearman-service.
- Go: github.com/mikespook/gearman-go.
- Node.js: node-gearman.
- C / C++: libgearman, already present on this instance.
The pattern is always the same. A worker calls add_function("name", handler) and loops. A client calls do("name", payload) for a synchronous result, or do_background("name", payload) to submit and return.
Scale by running more worker processes, on this instance or on other hosts, against the one job server.
Replacing the status console certificate
The console uses a self-signed certificate issued at first boot, which is why curl -k appears above. To use your own certificate, replace these two files and reload nginx:
sudo install -o root -g root -m 0644 your-certificate.crt /etc/nginx/tls/gearman.crt
sudo install -o root -g root -m 0600 your-private-key.key /etc/nginx/tls/gearman.key
sudo nginx -t sudo systemctl reload nginxChanging the status console password
The console password lives in /etc/nginx/gearman-status.htpasswd, bcrypt-hashed. To rotate it, generate a new entry. Then update the credentials file, so the value on the instance stays accurate:
NEWPW="$(openssl rand -base64 48 | tr -dc 'A-Za-z0-9' | cut -c1-28)" sudo htpasswd -nbB status "$NEWPW" | sudo tee /etc/nginx/gearman-status.htpasswd >/dev/null
sudo chown root:www-data /etc/nginx/gearman-status.htpasswd
sudo chmod 640 /etc/nginx/gearman-status.htpasswd
sudo systemctl reload nginx echo "new password: $NEWPW"Troubleshooting
The job server will not start. Check the unit log. The most common cause is a GEARMAND_LISTEN value that is not an address on this instance.
sudo systemctl is-active gearman-job-serveractiveIf it is not active, run sudo journalctl -u gearman-job-server -n 50 --no-pager on your instance to see why.
A client hangs and never gets a result. There is no worker registered for that function name. Check the queue. A function with a worker count of zero has nothing to run it.
The status console returns 401 with the right password. First boot may not have completed. Confirm that the sentinel exists, then re-read the credentials file.
sudo test -f /var/lib/sac/data/gearmand-firstboot.done && echo "first boot completed"first boot completedBackground jobs disappear after a restart. They should not, because that is what the persistent queue is for. Confirm that the queue database is present and on the dedicated volume with the commands in Step 13.
Support
SecureAnyCloud provides 24/7 technical support by email and live chat for this product. Support covers deployment, exposing the job server safely to your own subnet, worker connectivity, persistent queue behaviour, status console access and sizing.
Email: sales@secureanycloud.com
Gearman is distributed under the BSD 3-Clause License. All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.
Deploy on AWS
Launch Gearman Job Server with 24/7 support from SecureAnyCloud.
View on Marketplace
Need help?
Our support team is available 24/7.
sales@secureanycloud.com