AX

AgileX Recruitment ATS

Huly Self-Hosted Setup Guide — A modern Applicant Tracking System for South African enterprise recruitment, aligned with the 2nth.ai Cloudflare architecture.

Huly v0.7.382 OrbStack / Docker CockroachDB Cloudflare Tunnel Resend Email SA / POPIA

1 Architecture Overview

The demonstrator aligns with the 2nth.ai Cloudflare-first architecture. For local testing, Cloudflare Tunnel is replaced by direct localhost access.

Cloudflare Edge (SSL / DDoS / CDN) — production only | outbound tunnel (cloudflared) v nginx reverse proxy :80 |- / → front:8080 (UI) |- /_accounts → account:3000 (Auth) |- /api/v1/ → transactor:3333 (Data / WebSocket) |- /_collaborator → collaborator:3078 (Realtime OT) | Docker Compose Stack |- front account transactor workspace |- collaborator fulltext rekoni stats kvs | Data Layer |- CockroachDB (SQL store) |- Elasticsearch (full-text search) |- MinIO (S3-compatible file storage) |- Redpanda (Kafka-compatible message broker)

2nth.ai Alignment

Layer2nth.aiHuly Demonstrator
Edge / CDNCloudflare Workers/PagesCloudflare Tunnel + CDN
DNS / SSLCloudflareCloudflare (Full SSL)
EmailResendResend (SMTP bridge)
AI AgentsClaude API via 2nth agentsClaude API (replaces OpenAI/Hulia)
DataD1 / KVCockroachDB + Elasticsearch + MinIO
HostingCloudflare edgeHetzner VPS (Docker) / local Mac

2 Prerequisites

OrbStack (macOS)

Lightweight Docker runtime for Mac. Much faster and lighter than Docker Desktop.

brew install orbstack
Git & Node.js

Required for cloning the repo and running seed scripts.

brew install git node
System Resources

The Huly stack requires 8 GB RAM minimum free. Elasticsearch alone reserves 1 GB heap. Close heavy apps before starting.

3 Local Docker Setup

Clone the Huly self-host repository

git clone https://github.com/hcengineering/huly-selfhost.git
cd huly-selfhost

Run quick setup

The --quick flag configures for localhost:8087, skips all prompts, generates secrets, and auto-starts all containers.

./setup.sh --quick

Wait for services to initialise

All 14 containers need ~60 seconds to fully start. Check status with:

docker compose ps # all services should show "Up"
docker compose logs -f # follow logs (Ctrl+C to exit)

Verify Huly is running

Open http://localhost:8087 in your browser. You should see the Huly login page.

14 Services Running

nginx, cockroach, redpanda, minio, elastic, rekoni, transactor, collaborator, account, workspace, front, fulltext, stats, kvs

4 Account & Workspace Creation

Create Admin Account (API)

curl -s -X POST "http://localhost:8087/_accounts" \
  -H "Content-Type: application/json" \
  -d '{"method": "signUp", "params": {
    "email": "admin@agilex.co.za",
    "password": "AgileX2024!",
    "firstName": "Craig",
    "lastName": "Sobey"
  }}'

Returns a JWT token for authenticated requests.

Create Workspace

# Use the token from signUp response
curl -s -X POST "http://localhost:8087/_accounts" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"method": "createWorkspace", "params": {
    "workspaceName": "AgileX Recruitment",
    "workspaceUrl": "agilex-recruitment"
  }}'

Returns a workspace token with the workspace UUID and URL.

Fix: Internal URL Resolution

The account service's STATS_URL must point to the internal Docker hostname, not localhost:8087 (unreachable inside containers). In compose.yml, change the account service environment:

- STATS_URL=http://stats:4900   # was: http://localhost:8087/_stats

Then restart: docker compose up -d account

5 Staff Onboarding (10 Members)

Each staff member is created in two steps: signUp (creates account) then invite + join (adds to workspace).

Step 1: Create Staff Accounts

# For each staff member:
curl -s -X POST "http://localhost:8087/_accounts" \
  -H "Content-Type: application/json" \
  -d '{"method": "signUp", "params": {
    "email": "thandi.mokoena@agilex.co.za",
    "password": "AgileX2024!",
    "firstName": "Thandi",
    "lastName": "Mokoena"
  }}'

Step 2: Create Invite Link (as workspace Owner)

curl -s -X POST "http://localhost:8087/_accounts" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OWNER_TOKEN" \
  -d '{"method": "createInviteLink", "params": {
    "email": "thandi.mokoena@agilex.co.za",
    "role": "OWNER",
    "expHours": 720
  }}'
# Returns: http://localhost:8087/login/join?inviteId=...

Step 3: Accept Invite (as the staff member)

# Extract inviteId from the URL, then:
curl -s -X POST "http://localhost:8087/_accounts" \
  -H "Content-Type: application/json" \
  -d '{"method": "join", "params": {
    "email": "thandi.mokoena@agilex.co.za",
    "password": "AgileX2024!",
    "inviteId": "INVITE_ID_HERE"
  }}'

Staff Directory

NameEmailRoleDepartmentAccess
Craig Sobeyadmin@agilex.co.zaPlatform AdminOwner
Thandi Mokoenathandi.mokoena@agilex.co.zaManaging DirectorLeadershipOwner
Pieter van der Merwepieter.vandermerwe@agilex.co.zaHead of RecruitmentLeadershipMaintainer
Naledi Khumalonaledi.khumalo@agilex.co.zaSenior Recruitment MgrLeadershipMaintainer
Siyanda Dlaminisiyanda.dlamini@agilex.co.zaBanking SpecialistConsultantsUser
James Reynoldsjames.reynolds@agilex.co.zaTech & AI SpecialistConsultantsUser
Fatima Patelfatima.patel@agilex.co.zaGraduate Programme LeadConsultantsUser
Bongani Ndlovubongani.ndlovu@agilex.co.zaRetail SpecialistConsultantsUser
Sarah O'Connorsarah.oconnor@agilex.co.zaPM SpecialistConsultantsUser
Mpho Sitholempho.sithole@agilex.co.zaResearch & SourcingSupportUser
Lerato Mahlangulerato.mahlangu@agilex.co.zaAdmin & CoordinationSupportUser

All staff passwords: AgileX2024!

6 Seed Recruitment Data

Data is seeded directly into CockroachDB using a Node.js script that generates SQL matching Huly's document schema (JSONB data column with class mixins).

Generate & Execute

# Generate SQL from seed script
node seed-recruitment.mjs > seed-data.sql

# Execute against CockroachDB
docker compose exec -T cockroach ./cockroach sql \
  --url="$DB_URL" < seed-data.sql

# Restart transactor to pick up new data
docker compose restart transactor

Client Organisations (10)

ClientIndustryCityHQ
Standard Bank GroupBankingJohannesburgSimmonds Street, JHB CBD
FirstRand LimitedBankingJohannesburgSandton
Absa GroupBankingJohannesburg15 Alice Lane, Sandton
Nedbank GroupBankingJohannesburg135 Rivonia Road, Sandton
Capitec BankBankingStellenbosch5 Quantum Street, Technopark
Shoprite HoldingsRetailCape TownBrackenfell
Woolworths HoldingsRetailCape Town93 Longmarket Street
Pick n Pay StoresRetailCape Town101 Roeland Street
The Foschini Group (TFG)RetailCape TownStanley Lewis Centre, Parow
Mr Price GroupRetailDurban65 Masabalala Yengwa Ave

Vacancies (15)

#TitleClientTypeSalary Range
1Senior AI/ML EngineerStandard BankPermanentR1.2M – R1.6M
2Data Scientist – Risk AnalyticsStandard BankPermanentR950K – R1.3M
3DevOps EngineerFirstRandContract 12moR850 – R1,100/hr
4Head of Digital BankingAbsaPermanentR2.5M – R3.2M
5Cybersecurity AnalystNedbankPermanentR750K – R1.0M
6Graduate Programme – Banking OpsCapitecGraduate 24moR320K – R380K
7Supply Chain DirectorShopritePermanentR2.0M – R2.8M
8E-Commerce Product ManagerWoolworthsPermanentR900K – R1.2M
9IT Project Manager (SAP S/4HANA)Pick n PayContract 18moR950 – R1,200/hr
10Senior BA – Retail BankingFirstRandPermanentR800K – R1.1M
11Cloud ArchitectAbsaPermanentR1.4M – R1.9M
12Store Operations ManagerTFGPermanentR650K – R850K
13Talent Acquisition PartnerMr PricePermanentR600K – R800K
14Graduate Programme – Data & AnalyticsShopriteGraduate 18moR300K – R350K
15Scrum Master – Digital TransformationNedbankContract 6moR750 – R950/hr

Candidates (30)

NameTitleCityVacancyStage
Nomvula ZuluML EngineerJohannesburgSenior AI/ML EngineerHired
Hendrik BothaSupply Chain ManagerCape TownSupply Chain DirectorHired
Ayanda MthembuBusiness AnalystDurbanSenior BA – Retail BankingHired
Priya NaidooCybersecurity AnalystJohannesburgCybersecurity AnalystHired
David PretoriusGraduate – Banking OpsStellenboschGraduate ProgrammeHired
Zanele NkosiCloud ArchitectJohannesburgCloud ArchitectOffer
Mohammed EssopE-Commerce PMCape TownE-Commerce Product MgrOffer
Lindiwe MasekoScrum MasterJohannesburgScrum MasterOffer
Tshepo MolefeDevOps EngineerPretoriaDevOps EngineerRef Check
Samantha WilliamsData ScientistJohannesburgData Scientist – RiskRef Check
Kabelo MotaungIT Project ManagerJohannesburgIT PM (SAP S/4HANA)Ref Check
Nkululeko HadebeAI EngineerDurbanSenior AI/ML EngineerTech Assessment
Annika van WykCloud Solutions ArchitectCape TownCloud ArchitectTech Assessment
Sipho MabasoSenior BA – PaymentsJohannesburgSenior BA – Retail BankingTech Assessment
Chantal de VilliersDigital Banking StrategistStellenboschHead of Digital BankingTech Assessment
Thabo LangaDevOps EngineerJohannesburgDevOps EngineerInterview
Precious MoyoTalent Acquisition PartnerPretoriaTalent Acquisition PartnerInterview
Ruan ErasmusStore Ops ManagerJohannesburgStore Operations ManagerInterview
Nosipho DubeGraduate – Data AnalyticsDurbanGraduate – Data & AnalyticsInterview
Michael SmithProduct ManagerCape TownE-Commerce Product MgrInterview
Busisiwe NgcoboRisk AnalystJohannesburgData Scientist – RiskScreening
Jean-Pierre du PlessisSAP ConsultantCape TownIT PM (SAP S/4HANA)Screening
Amahle CeleGraduate – BankingDurbanGraduate ProgrammeScreening
Stefan JoubertScrum MasterJohannesburgScrum MasterScreening
Mandisa SibiyaML/AI ResearcherJohannesburgSenior AI/ML EngineerSourced
Willem SwartSecurity EngineerPretoriaCybersecurity AnalystSourced
Thandeka MkhizeHead of DigitalJohannesburgHead of Digital BankingSourced
Grant ThompsonDevOps EngineerCape TownDevOps EngineerRejected
Nomfundo ZwaneBA – PaymentsJohannesburgSenior BARejected
Andre FourieSupply Chain AnalystStellenboschSupply Chain DirectorWithdrawn

7 Data Summary

11
Staff Members
10
Client Orgs
15
Vacancies
30
Candidates
3
HR Departments
9
Pipeline Stages

Candidate Pipeline Distribution

StageCountDescription
Sourced3Identified, not yet contacted
Screening4CV review and initial phone screen
Interview5First or second interview with client
Tech Assessment4Technical test or case study
Ref Check3Reference verification in progress
Offer3Offer extended, awaiting acceptance
Hired5Offer accepted, placement confirmed
Rejected2Did not proceed
Withdrawn1Candidate withdrew

8 Login Reference

Admin Login

Email: admin@agilex.co.za

Password: AgileX2024!

Staff Login (all accounts)

Email: firstname.lastname@agilex.co.za

Password: AgileX2024!

Huly Modules to Explore

Recruit — vacancies, candidate applications, pipeline board
HR — departments, staff records, org structure
Contacts — client organisations, all persons
Tracker — task management for recruitment workflow

9 Next Steps

Configure Resend for Email

Add a mail service to compose.yml with Resend SMTP credentials. Resend provides a free tier with 100 emails/day. Use smtp.resend.com:587 as SMTP host with your Resend API key as password.

Set Up Cloudflare Tunnel

Install cloudflared, create a tunnel, and route DNS for recruit.agilex.co.za. Zero inbound ports exposed, SSL termination at Cloudflare edge. See huly/cloudflare-tunnel.md.

Deploy to Hetzner VPS

Provision a CPX31 (4 vCPU, 8 GB RAM, ~R280/mo) in Falkenstein. Mirror the local Docker setup. See huly/hetzner-setup.md.

Replace OpenAI with Claude API

Swap the OPENAI_API_KEY in the aibot service for a Claude API integration via 2nth.ai agents, providing AI-powered candidate screening and communication.

Disable Public Signup

Set DISABLE_SIGNUP=true on both front and account services. New users join only via invite links.

POPIA Compliance

Add privacy notice and data processing agreement. All data stays on your infrastructure (Hetzner EU). Configure data retention policies for candidate records.