This repo is a monorepo for the Daily Auction system.
- If needed: Create IAM user on AWS (details below).
- Copy
.env.templateto.envand fill in the AWS values (buckets, domains, region). - Run the AWS setup script:
./scripts/setup-aws.shAdd the DNS validation CNAMEs in your DNS provider, wait for the cert to be ISSUED, set ACM_CERT_ARN in .env, then re-run ./scripts/setup-aws.sh.
After scripts/setup-aws.sh, it prints the CloudFront domains. Create DNS records:
preview.thedailyauction.app→ CNAME to the preview CloudFront domainwww.thedailyauction.app→ CNAME to the prod CloudFront domaineditor.thedailyauction.com→ CNAME to the editor CloudFront domain
- Start local services:
docker compose up --buildCodex listens on http://localhost:8080. Deploy listens on the internal Docker network only.
Codex env vars (in .env):
OPENAI_API_KEY(required for HTML-only edits)HTML_EDIT_MIN_CHARS(optional, default200)HTML_EDIT_MAX_CHARS(optional, default2000000)HTML_EDIT_TIMEOUT_SECONDS(optional, default180)AUCTION_PROGRAM_ID(required to authorize yesterday's winner - set in step 6)RPC_URL(optional, default devnet)
- Run the editor locally using your master wallet:
cd editor
python3 -m http.server 8000
Production hosting notes:
- Deploy Codex + Deploy on a single EC2 instance with Docker Compose (Codex public, Deploy internal-only). Other setups are possible, but EC2 is the assumed default.
- You need both ports 80 and 443 open
- There is a convenience helper to set things up within the EC2 instance:
sudo DOMAIN=api.thedailyauction.com ./scripts/setup-ec2.sh - The A record of
api.thedailyauction.comshould point to the Elastic IP of the EC2 instance, which forwards to the Codex server. - Keep Deploy internal-only.
- Run
./scripts/publish-editor.shto deploy the editor remotely
- Deploy the Solana auction program (Anchor)
Location: programs/auction.
Initialize the program ID (generates target/deploy/auction-keypair.json if missing
and updates Anchor.toml + programs/auction/src/lib.rs):
./scripts/init-auction-program.shSet your program ID in .env (needed for the nightly job below).
Build with:
cd programs/auction
anchor buildCreate a deploy wallet (and optionally reuse it as the cranker wallet):
solana-keygen new -o ~/.config/solana/auction-operator.jsonThen set CRANKER_PRIVATE_KEY and AUCTION_RECIPIENT_PUBKEY in your .env
(use an absolute path; ~ won’t expand when sourced):
CRANKER_PRIVATE_KEY="$(cat /Users/YOUR_USER/.config/solana/auction-operator.json)"
AUCTION_RECIPIENT_PUBKEY=9ajQ4mq9cxTqTDT8b2LyQGnooAbwgFdPn72xkWdSdj5SRPC configuration:
- Anchor uses the cluster in
Anchor.tomlunder[provider](e.g.DevnetorMainnet). - Update the
walletfield inAnchor.tomlto point at your deploy keypair. - Make sure you point at either devnet or mainnet RPC depending on what you want to do.
Devnet SOL for deploy + cranker wallets:
solana config set --url https://api.devnet.solana.com
solana airdrop 1 ~/.config/solana/auction-operator.json
solana airdrop 1 /path/to/cranker-keypair.json
# Request more SOL at https://faucet.solana.com/If you use the same keypair for deploy and cranker, a single airdrop to that keypair is enough.
Deploy with:
cd programs/auction
anchor deployThe program implements the spec in docs/solana-auction-spec.md.
At this point, you can set AUCTION_PROGRAM_ID in your .env. Your local Codex container will allow the on-chain auction winner to make edits.
- Deploy the nightly settlement job to AWS Lambda
Location: jobs/auction_settlement.
The Lambda entrypoint is jobs/auction_settlement/handler.py.
Initialize the config (one-time, before running the nightly job):
python3 -m venv .venv
source .venv/bin/activate
pip install -r jobs/auction_settlement/requirements.txt
set -a && source .env && set +a
python3 scripts/init-auction-config.pyTest the lambda function locally:
python3 jobs/auction_settlement/handler.pyDeployment script:
./scripts/deploy-auction-lambda.shRequired env vars:
AUCTION_PROGRAM_IDCRANKER_PRIVATE_KEY(base58 or JSON array secret key - must be in quotes)
Optional env vars:
RPC_URL(default devnet - match the Anchor deployment above)MAX_BATCH_SIZE(default 20)RETRY_WINDOW_SECONDS(default 1800)RETRY_INTERVAL_SECONDS(default 45)MAX_RUNTIME_SECONDS(default 780)MASTER_WALLET(pubkey that can do any operation on the editor)CODEX_NUKE_URL(optional, triggers Codex nuke after settlement)MASTER_WALLET_PRIVATE_KEY(required for nuke signing)
- Test the public auction website (Next.js)
Location: public-auction.
Public site env vars (set in public-auction/.env.local):
NEXT_PUBLIC_AUCTION_PROGRAM_IDNEXT_PUBLIC_RPC_URL(default devnet)NEXT_PUBLIC_DISABLE_SITE
You can start from public-auction/.env.local.example.
Node.js version >= v18.17.0 is required.
cd public-auction
npm install
npm run devRecommended: If you run scripts/setup-aws.sh and scripts/deploy-auction-lambda.sh with the same IAM user,
attach a single inline policy that includes S3 + CloudFront + ACM + IAM + Lambda + EventBridge permissions.
Adjust bucket names and function/role names if you changed them.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AcmCert",
"Effect": "Allow",
"Action": [
"acm:RequestCertificate",
"acm:DeleteCertificate",
"acm:DescribeCertificate",
"acm:ListCertificates"
],
"Resource": "*"
},
{
"Sid": "CloudFront",
"Effect": "Allow",
"Action": [
"cloudfront:CreateDistribution",
"cloudfront:GetDistribution",
"cloudfront:GetDistributionConfig",
"cloudfront:ListDistributions",
"cloudfront:UpdateDistribution",
"cloudfront:CreateCachePolicy",
"cloudfront:ListCachePolicies",
"cloudfront:CreateOriginAccessControl",
"cloudfront:ListOriginAccessControls",
"cloudfront:ListResponseHeadersPolicies",
"cloudfront:CreateResponseHeadersPolicy",
"cloudfront:GetResponseHeadersPolicy",
"cloudfront:GetResponseHeadersPolicyConfig"
],
"Resource": "*"
},
{
"Sid": "S3",
"Effect": "Allow",
"Action": [
"s3:CreateBucket",
"s3:PutBucketPolicy",
"s3:PutBucketPublicAccessBlock",
"s3:PutBucketOwnershipControls",
"s3:ListBucket",
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::thedailyauction-preview",
"arn:aws:s3:::thedailyauction-prod",
"arn:aws:s3:::thedailyauction-editor",
"arn:aws:s3:::thedailyauction-preview/*",
"arn:aws:s3:::thedailyauction-prod/*",
"arn:aws:s3:::thedailyauction-editor/*"
]
},
{
"Sid": "StsIdentity",
"Effect": "Allow",
"Action": ["sts:GetCallerIdentity"],
"Resource": "*"
},
{
"Sid": "IamRoleManagement",
"Effect": "Allow",
"Action": [
"iam:CreateRole",
"iam:GetRole",
"iam:AttachRolePolicy",
"iam:PassRole"
],
"Resource": "arn:aws:iam::*:role/AuctionLambdaExecutionRole"
},
{
"Sid": "LambdaManagement",
"Effect": "Allow",
"Action": [
"lambda:CreateFunction",
"lambda:GetFunction",
"lambda:UpdateFunctionCode",
"lambda:UpdateFunctionConfiguration",
"lambda:AddPermission"
],
"Resource": "arn:aws:lambda:*:*:function:auction-settlement-daily"
},
{
"Sid": "EventBridgeManagement",
"Effect": "Allow",
"Action": [
"events:PutRule",
"events:PutTargets"
],
"Resource": "*"
}
]
}codex: Control plane for edit/deploy/nuke and the staticsite/working tree.deploy: Internal-only deploy service that owns the baseline and publishes to S3.site-template: Baseline static site template for nukes and initialization.editor: Static wallet-connected editor UI for local testing.programs/auction: Anchor-based Solana auction program.jobs/auction_settlement: Python AWS Lambda job for nightly settlement and refunds.public-auction: Next.js public auction wrapper site.
Requests to /edit, /deploy, and /nuke require these headers:
X-Wallet: base58 Solana public key (currently must matchMASTER_WALLET)X-Nonce: unique per requestX-Expiry: unix epoch secondsX-Signature: base58 signature of the message
Message format (bytes):
{wallet}:{nonce}:{expiry}:{path}:{sha256(body)}