diff --git a/apps/academy/public/assets/tracks/arweave-201/2/figure-1.png b/apps/academy/public/assets/tracks/arweave-201/2/figure-1.png new file mode 100644 index 00000000..5aa20a80 Binary files /dev/null and b/apps/academy/public/assets/tracks/arweave-201/2/figure-1.png differ diff --git a/apps/academy/public/meta-images/arweave-201/deploying-an-arweave-gateway-to-the-cloud-for-production.png b/apps/academy/public/meta-images/arweave-201/deploying-an-arweave-gateway-to-the-cloud-for-production.png new file mode 100644 index 00000000..c86b78ed Binary files /dev/null and b/apps/academy/public/meta-images/arweave-201/deploying-an-arweave-gateway-to-the-cloud-for-production.png differ diff --git a/apps/academy/src/data/questions/arweave-201/1/quiz-1/Q1.json b/apps/academy/src/data/questions/arweave-201/1/quiz-1/Q1.json index f97e4cad..a18423b5 100644 --- a/apps/academy/src/data/questions/arweave-201/1/quiz-1/Q1.json +++ b/apps/academy/src/data/questions/arweave-201/1/quiz-1/Q1.json @@ -1,20 +1,16 @@ { - "question": "What is Arweave?", + "question": "What types of Arweave nodes exist?", "options": [ { - "answer": "A layer 1 network", + "answer": "Miner nodes.", "correct": true }, { - "answer": "A layer 2 network" - }, - { - "answer": "Like Bitcoin for storage", + "answer": "Gateway nodes.", "correct": true }, { - "answer": "Immutable object storage", - "correct": true + "answer": "Swap nodes." } ] } diff --git a/apps/academy/src/data/questions/arweave-201/1/quiz-1/Q2.json b/apps/academy/src/data/questions/arweave-201/1/quiz-1/Q2.json index bb3f2ce7..31983075 100644 --- a/apps/academy/src/data/questions/arweave-201/1/quiz-1/Q2.json +++ b/apps/academy/src/data/questions/arweave-201/1/quiz-1/Q2.json @@ -1,19 +1,15 @@ { - "question": "What features does Arweave have?", + "question": "How are AR.IO gateway operators incentivized?", "options": [ { - "answer": "Censorship resistance", + "answer": "With IO tokens generated from ArNS sales.", "correct": true }, { - "answer": "Global replication", - "correct": true - }, - { - "answer": "Temporary storage" + "answer": "With Arweave's native AR token." }, { - "answer": "Automatic encryption" + "answer": "They do it for the greater good." } ] } diff --git a/apps/academy/src/data/questions/arweave-201/1/quiz-1/Q3.json b/apps/academy/src/data/questions/arweave-201/1/quiz-1/Q3.json index 70d03a6f..68c19fdc 100644 --- a/apps/academy/src/data/questions/arweave-201/1/quiz-1/Q3.json +++ b/apps/academy/src/data/questions/arweave-201/1/quiz-1/Q3.json @@ -1,20 +1,15 @@ { - "question": "What data can you store on Arweave?", + "question": "How are AR.IO gateways implemented?", "options": [ { - "answer": "Music and videos", + "answer": "They are Node.js containers running on Docker Compose.", "correct": true }, { - "answer": "Images and text", - "correct": true - }, - { - "answer": "Single page applications", - "correct": true + "answer": "They use Java Server Pages and Nginx." }, { - "answer": "Server-side rendered websites" + "answer": "They are written in Rust." } ] } diff --git a/apps/academy/src/data/questions/arweave-201/1/quiz-2/Q1.json b/apps/academy/src/data/questions/arweave-201/1/quiz-2/Q1.json index dac085b9..b41f69e7 100644 --- a/apps/academy/src/data/questions/arweave-201/1/quiz-2/Q1.json +++ b/apps/academy/src/data/questions/arweave-201/1/quiz-2/Q1.json @@ -1,16 +1,16 @@ { - "question": "Where does Arweave store files?", + "question": "Which files do you need to start an AR.IO gateway?", "options": [ { - "answer": "Everything is stored in the transaction object" + "answer": "The docker-compose.yaml.", + "correct": true }, { - "answer": "The transaction object can contain files smaller than 12MiB", + "answer": "An .env file.", "correct": true }, { - "answer": "Files bigger than 12MiB have a separate storage location", - "correct": true + "answer": "A MAKE file." } ] } diff --git a/apps/academy/src/data/questions/arweave-201/1/quiz-2/Q2.json b/apps/academy/src/data/questions/arweave-201/1/quiz-2/Q2.json index a874c9d0..3a077ce9 100644 --- a/apps/academy/src/data/questions/arweave-201/1/quiz-2/Q2.json +++ b/apps/academy/src/data/questions/arweave-201/1/quiz-2/Q2.json @@ -1,16 +1,15 @@ { - "question": "How does Arweave’s consensus algorithm ensure permanent storage?", + "question": "Why should you not start the writer processes?", "options": [ { - "answer": "By requiring miner nodes to prove access to random chunks of uploaded data", + "answer": "Because they will start indexing the whole chain, which can take weeks.", "correct": true }, { - "answer": "By incentivizing miner nodes to share data", - "correct": true + "answer": "Because you have to pay for each byte downloaded from Arweave." }, { - "answer": "By encrypting transaction bodies before upload" + "answer": "Because they will mine Bitcoin on your machine." } ] } diff --git a/apps/academy/src/data/questions/arweave-201/1/quiz-2/Q3.json b/apps/academy/src/data/questions/arweave-201/1/quiz-2/Q3.json index 617cdfe3..42ef8244 100644 --- a/apps/academy/src/data/questions/arweave-201/1/quiz-2/Q3.json +++ b/apps/academy/src/data/questions/arweave-201/1/quiz-2/Q3.json @@ -1,19 +1,16 @@ { - "question": "What responsibilities do miner nodes have?", + "question": "Why do you need to set a trusted node?", "options": [ { - "answer": "Data storage", + "answer": "The trusted node is your entry to the Arweave network.", "correct": true }, { - "answer": "Data replication", + "answer": "The trusted node will resolve all data your gateway hasn't indexed/cached yet.", "correct": true }, { - "answer": "Data access" - }, - { - "answer": "Data encoding" + "answer": "The trusted node will help you encrypting uploaded data." } ] } diff --git a/apps/academy/src/data/questions/arweave-201/1/quiz-3/Q1.json b/apps/academy/src/data/questions/arweave-201/1/quiz-3/Q1.json index 92823d5c..cb8012ac 100644 --- a/apps/academy/src/data/questions/arweave-201/1/quiz-3/Q1.json +++ b/apps/academy/src/data/questions/arweave-201/1/quiz-3/Q1.json @@ -1,16 +1,12 @@ { - "question": "What are parts of the SPoRA consensus algorithm?", + "question": "Why do you need to stop the gateway explicitly?", "options": [ { - "answer": "Computing a hash", + "answer": "Because Docker Compose will run the gateway in the background.", "correct": true }, { - "answer": "Proving access to random chunks of uploaded data", - "correct": true - }, - { - "answer": "Locking sectors of a block storage" + "answer": "You don't have to stop it, it will stop automatically after 5 minutes." } ] } diff --git a/apps/academy/src/data/questions/arweave-201/1/quiz-3/Q2.json b/apps/academy/src/data/questions/arweave-201/1/quiz-3/Q2.json index 5b76633f..62b78fab 100644 --- a/apps/academy/src/data/questions/arweave-201/1/quiz-3/Q2.json +++ b/apps/academy/src/data/questions/arweave-201/1/quiz-3/Q2.json @@ -1,16 +1,16 @@ { - "question": "How can you remove data from Arweave?", + "question": "Why should you enable HTTPS for your server?", "options": [ { - "answer": "By sending a do-not-store request", + "answer": "Because some browser APIs don't work without HTTPS.", "correct": true }, { - "answer": "You can’t enforce removal", + "answer": "To prevent third-parties from reading your users data.", "correct": true }, { - "answer": "By forking the chain" + "answer": "To save traffic." } ] } diff --git a/apps/academy/src/data/questions/arweave-201/1/quiz-3/Q3.json b/apps/academy/src/data/questions/arweave-201/1/quiz-3/Q3.json index b64eabb4..fe94f613 100644 --- a/apps/academy/src/data/questions/arweave-201/1/quiz-3/Q3.json +++ b/apps/academy/src/data/questions/arweave-201/1/quiz-3/Q3.json @@ -1,19 +1,15 @@ { - "question": "How does Arweave ensure continuous payment for its storage?", + "question": "How do you disable sandboxing?", "options": [ { - "answer": "It has a storage endowment to save tokens for later", + "answer": "By not setting a ARNS_ROOT_HOST in your .env file.", "correct": true }, { - "answer": "Its token economics are based on future storage cost estimates", - "correct": true - }, - { - "answer": "It gives each miner node one Bitcoin" + "answer": "By setting SANDBOXING to false in your .env file." }, { - "answer": "It requires continuous payments." + "answer": "By using a ?sandbox=false query parameter when opening a TX." } ] } diff --git a/apps/academy/src/data/questions/arweave-201/1/quiz-4/Q1.json b/apps/academy/src/data/questions/arweave-201/1/quiz-4/Q1.json index 7bc76a65..fe5e59f5 100644 --- a/apps/academy/src/data/questions/arweave-201/1/quiz-4/Q1.json +++ b/apps/academy/src/data/questions/arweave-201/1/quiz-4/Q1.json @@ -1,16 +1,15 @@ { - "question": "What are the Arweave transaction types?", + "question": "What do you have to remember when enbaling the writers?", "options": [ { - "answer": "L1 transactions", + "answer": "To set a START_HEIGHT value so the writers don't index the whole chain.", "correct": true }, { - "answer": "Bundled transactions", - "correct": true + "answer": "To set a TIMEOUT value, so they don't wait for pending transacitons." }, { - "answer": "Volatile transactions" + "answer": "Nothing, you can simply set START_WRITERS to true and acccess new transactions right away." } ] } diff --git a/apps/academy/src/data/questions/arweave-201/1/quiz-4/Q2.json b/apps/academy/src/data/questions/arweave-201/1/quiz-4/Q2.json index dbf1220d..f16d0dc1 100644 --- a/apps/academy/src/data/questions/arweave-201/1/quiz-4/Q2.json +++ b/apps/academy/src/data/questions/arweave-201/1/quiz-4/Q2.json @@ -1,20 +1,15 @@ { - "question": "What are the properties of L1 transactions?", + "question": "Under which route are the admin features located?", "options": [ { - "answer": "They are relatively slow", + "answer": "/ar-io/admin/...", "correct": true }, { - "answer": "They can transfer AR tokens", - "correct": true - }, - { - "answer": "They can be paid with fiat currency" + "answer": "/admin" }, { - "answer": "They can have custom tags", - "correct": true + "answer": "/gatetway/admin" } ] } diff --git a/apps/academy/src/data/questions/arweave-201/1/quiz-4/Q3.json b/apps/academy/src/data/questions/arweave-201/1/quiz-4/Q3.json index 5a99c014..b5e560f6 100644 --- a/apps/academy/src/data/questions/arweave-201/1/quiz-4/Q3.json +++ b/apps/academy/src/data/questions/arweave-201/1/quiz-4/Q3.json @@ -1,20 +1,12 @@ { - "question": "What are the properties of bundled transactions?", + "question": "Should you run an observer for your dev gateway?", "options": [ { - "answer": "They are relatively fast", + "answer": "No, they're only for production gateways.", "correct": true }, { - "answer": "They can be paid with fiat currency", - "correct": true - }, - { - "answer": "They can transfer AR tokens" - }, - { - "answer": "They can have custom tags", - "correct": true + "answer": "Yes, they can improve performance." } ] } diff --git a/apps/academy/src/data/questions/arweave-201/1/quiz-5/Q1.json b/apps/academy/src/data/questions/arweave-201/1/quiz-5/Q1.json index 3965ca3c..b3acbcd9 100644 --- a/apps/academy/src/data/questions/arweave-201/1/quiz-5/Q1.json +++ b/apps/academy/src/data/questions/arweave-201/1/quiz-5/Q1.json @@ -1,19 +1,16 @@ { - "question": "What are Arweave's pros compared to cloud storage?", + "question": "Can multiple gateways reuse data?", "options": [ { - "answer": "One-time payment", + "answer": "Yes, but only CHUNKS_DATA_PATH, CONTIGUOUS_DATA_PATH, and HEADERS_DATA_PATH.", "correct": true }, { - "answer": "Strong provenance guarantees", + "answer": "Yes, but only one gateway should have START_WRITERS.", "correct": true }, { - "answer": "Temporary storage" - }, - { - "answer": "Cheap storage" + "answer": "No, all data is unique to a gateway." } ] } diff --git a/apps/academy/src/data/questions/arweave-201/1/quiz-5/Q2.json b/apps/academy/src/data/questions/arweave-201/1/quiz-5/Q2.json index 4e3beb99..c3628c87 100644 --- a/apps/academy/src/data/questions/arweave-201/1/quiz-5/Q2.json +++ b/apps/academy/src/data/questions/arweave-201/1/quiz-5/Q2.json @@ -1,19 +1,15 @@ { - "question": "What are Arweave’s pros compared to popular blockchain networks?", + "question": "Can you use webhooks without unbundling transactions?", "options": [ { - "answer": "Cheap permanent storage", + "answer": "Yes, but only for layer 1 transactions and blocks.", "correct": true }, { - "answer": "The protocol handles storage and replication", - "correct": true - }, - { - "answer": "Temporary storage" + "answer": "No, you need to activate it to use webhooks." }, { - "answer": "Fast L1 transactions" + "answer": "Yes, they will trigger on all transactions." } ] } diff --git a/apps/academy/src/data/questions/arweave-201/2/quiz-5/Q3.json b/apps/academy/src/data/questions/arweave-201/1/quiz-5/Q3.json similarity index 100% rename from apps/academy/src/data/questions/arweave-201/2/quiz-5/Q3.json rename to apps/academy/src/data/questions/arweave-201/1/quiz-5/Q3.json diff --git a/apps/academy/src/data/questions/arweave-201/2/quiz-1/Q1.json b/apps/academy/src/data/questions/arweave-201/2/quiz-1/Q1.json index a18423b5..36051569 100644 --- a/apps/academy/src/data/questions/arweave-201/2/quiz-1/Q1.json +++ b/apps/academy/src/data/questions/arweave-201/2/quiz-1/Q1.json @@ -1,16 +1,16 @@ { - "question": "What types of Arweave nodes exist?", + "question": "Why does your gateway need a domain?", "options": [ { - "answer": "Miner nodes.", + "answer": "To enable sandboxing via dynamic subdomains.", "correct": true }, { - "answer": "Gateway nodes.", + "answer": "To enable human-friendly ArNS names.", "correct": true }, { - "answer": "Swap nodes." + "answer": "To improve latency and reliability." } ] } diff --git a/apps/academy/src/data/questions/arweave-201/2/quiz-1/Q2.json b/apps/academy/src/data/questions/arweave-201/2/quiz-1/Q2.json index 31983075..25ea7c56 100644 --- a/apps/academy/src/data/questions/arweave-201/2/quiz-1/Q2.json +++ b/apps/academy/src/data/questions/arweave-201/2/quiz-1/Q2.json @@ -1,15 +1,17 @@ { - "question": "How are AR.IO gateway operators incentivized?", + "question": "Why does this setup include a load balancer?", "options": [ { - "answer": "With IO tokens generated from ArNS sales.", + "answer": "To distribute the load between two EC2 instances.", "correct": true }, { - "answer": "With Arweave's native AR token." + "answer": "To protect the EC2 instances with a web application firewall.", + "correct": true }, { - "answer": "They do it for the greater good." + "answer": "To improve reliability.", + "correct": true } ] } diff --git a/apps/academy/src/data/questions/arweave-201/2/quiz-1/Q3.json b/apps/academy/src/data/questions/arweave-201/2/quiz-1/Q3.json index 68c19fdc..7c2223ed 100644 --- a/apps/academy/src/data/questions/arweave-201/2/quiz-1/Q3.json +++ b/apps/academy/src/data/questions/arweave-201/2/quiz-1/Q3.json @@ -1,15 +1,15 @@ { - "question": "How are AR.IO gateways implemented?", + "question": "What is the job of CodeDeploy in this setup?", "options": [ { - "answer": "They are Node.js containers running on Docker Compose.", + "answer": "It will update the gateway when a new version is released.", "correct": true }, { - "answer": "They use Java Server Pages and Nginx." + "answer": "It will deploy the gateway." }, { - "answer": "They are written in Rust." + "answer": "It will check the health of the deployment." } ] } diff --git a/apps/academy/src/data/questions/arweave-201/2/quiz-2/Q1.json b/apps/academy/src/data/questions/arweave-201/2/quiz-2/Q1.json index b41f69e7..2d3551fd 100644 --- a/apps/academy/src/data/questions/arweave-201/2/quiz-2/Q1.json +++ b/apps/academy/src/data/questions/arweave-201/2/quiz-2/Q1.json @@ -1,16 +1,15 @@ { - "question": "Which files do you need to start an AR.IO gateway?", + "question": "Which wallet key will be stored on AWS?", "options": [ { - "answer": "The docker-compose.yaml.", - "correct": true + "answer": "The gateway key." }, { - "answer": "An .env file.", + "answer": "The observer key.", "correct": true }, { - "answer": "A MAKE file." + "answer": "The master key." } ] } diff --git a/apps/academy/src/data/questions/arweave-201/2/quiz-2/Q2.json b/apps/academy/src/data/questions/arweave-201/2/quiz-2/Q2.json index 3a077ce9..0bf639d9 100644 --- a/apps/academy/src/data/questions/arweave-201/2/quiz-2/Q2.json +++ b/apps/academy/src/data/questions/arweave-201/2/quiz-2/Q2.json @@ -1,15 +1,15 @@ { - "question": "Why should you not start the writer processes?", + "question": "Do you have to host your gateway on a second-level domain?", "options": [ { - "answer": "Because they will start indexing the whole chain, which can take weeks.", - "correct": true + "answer": "Yes, it has to be a second-level domain." }, { - "answer": "Because you have to pay for each byte downloaded from Arweave." + "answer": "No, you can use a subdomain.", + "correct": true }, { - "answer": "Because they will mine Bitcoin on your machine." + "answer": "No, you can use an ENS domain." } ] } diff --git a/apps/academy/src/data/questions/arweave-201/2/quiz-2/Q3.json b/apps/academy/src/data/questions/arweave-201/2/quiz-2/Q3.json index 42ef8244..f7c2eee3 100644 --- a/apps/academy/src/data/questions/arweave-201/2/quiz-2/Q3.json +++ b/apps/academy/src/data/questions/arweave-201/2/quiz-2/Q3.json @@ -1,16 +1,17 @@ { - "question": "Why do you need to set a trusted node?", + "question": "Why does the gateway use two wallet addresses?", "options": [ { - "answer": "The trusted node is your entry to the Arweave network.", + "answer": "One key is used to join the AR.IO network.", "correct": true }, { - "answer": "The trusted node will resolve all data your gateway hasn't indexed/cached yet.", + "answer": "One is used to submit reports to Arweave.", "correct": true }, { - "answer": "The trusted node will help you encrypting uploaded data." + "answer": "You can use the same key for joining the network and submit reports.", + "correct": true } ] } diff --git a/apps/academy/src/data/questions/arweave-201/2/quiz-3/Q1.json b/apps/academy/src/data/questions/arweave-201/2/quiz-3/Q1.json index cb8012ac..f6894e99 100644 --- a/apps/academy/src/data/questions/arweave-201/2/quiz-3/Q1.json +++ b/apps/academy/src/data/questions/arweave-201/2/quiz-3/Q1.json @@ -1,12 +1,15 @@ { - "question": "Why do you need to stop the gateway explicitly?", + "question": "Why does the first deplyoment run fail?", "options": [ { - "answer": "Because Docker Compose will run the gateway in the background.", + "answer": "Because AWS can't vaildate the SSL certificates.", "correct": true }, { - "answer": "You don't have to stop it, it will stop automatically after 5 minutes." + "answer": "Because you didn't assign a cost center." + }, + { + "answer": "Because SSL certificate validation always times out." } ] } diff --git a/apps/academy/src/data/questions/arweave-201/2/quiz-3/Q2.json b/apps/academy/src/data/questions/arweave-201/2/quiz-3/Q2.json index 62b78fab..ddda9e63 100644 --- a/apps/academy/src/data/questions/arweave-201/2/quiz-3/Q2.json +++ b/apps/academy/src/data/questions/arweave-201/2/quiz-3/Q2.json @@ -1,16 +1,16 @@ { - "question": "Why should you enable HTTPS for your server?", + "question": "Why does the gateway need two DNS records?", "options": [ { - "answer": "Because some browser APIs don't work without HTTPS.", + "answer": "One record is required for the domain root of the gateway.", "correct": true }, { - "answer": "To prevent third-parties from reading your users data.", - "correct": true + "answer": "One record is required for wallet verification." }, { - "answer": "To save traffic." + "answer": "The wildcard record is required for sandboxing and ArNS name resolution.", + "correct": true } ] } diff --git a/apps/academy/src/data/questions/arweave-201/2/quiz-3/Q3.json b/apps/academy/src/data/questions/arweave-201/2/quiz-3/Q3.json index fe94f613..bead84ab 100644 --- a/apps/academy/src/data/questions/arweave-201/2/quiz-3/Q3.json +++ b/apps/academy/src/data/questions/arweave-201/2/quiz-3/Q3.json @@ -1,15 +1,15 @@ { - "question": "How do you disable sandboxing?", + "question": "What's the path of the health check enpoint??", "options": [ { - "answer": "By not setting a ARNS_ROOT_HOST in your .env file.", + "answer": "/ar-io/healthcheck", "correct": true }, { - "answer": "By setting SANDBOXING to false in your .env file." + "answer": "/health-check" }, { - "answer": "By using a ?sandbox=false query parameter when opening a TX." + "answer": "/ar-io/status" } ] } diff --git a/apps/academy/src/data/questions/arweave-201/2/quiz-4/Q1.json b/apps/academy/src/data/questions/arweave-201/2/quiz-4/Q1.json index fe5e59f5..035d381d 100644 --- a/apps/academy/src/data/questions/arweave-201/2/quiz-4/Q1.json +++ b/apps/academy/src/data/questions/arweave-201/2/quiz-4/Q1.json @@ -1,15 +1,15 @@ { - "question": "What do you have to remember when enbaling the writers?", + "question": "How many images will CodeDeploy build on an update?", "options": [ { - "answer": "To set a START_HEIGHT value so the writers don't index the whole chain.", - "correct": true + "answer": "Three, one for Envoy, one for the gateway node, and one for the observer." }, { - "answer": "To set a TIMEOUT value, so they don't wait for pending transacitons." + "answer": "None, all are pulled from a image registry.", + "correct": true }, { - "answer": "Nothing, you can simply set START_WRITERS to true and acccess new transactions right away." + "answer": "It just builds the ones that have changed." } ] } diff --git a/apps/academy/src/data/questions/arweave-201/2/quiz-4/Q2.json b/apps/academy/src/data/questions/arweave-201/2/quiz-4/Q2.json index f16d0dc1..4957225b 100644 --- a/apps/academy/src/data/questions/arweave-201/2/quiz-4/Q2.json +++ b/apps/academy/src/data/questions/arweave-201/2/quiz-4/Q2.json @@ -1,15 +1,16 @@ { - "question": "Under which route are the admin features located?", + "question": "How long is your gateway unavailable during an update?", "options": [ { - "answer": "/ar-io/admin/...", + "answer": "It's never unavailable, as there is only one instance updated at a time.", "correct": true }, { - "answer": "/admin" + "answer": "All in all, 30 minutes." }, { - "answer": "/gatetway/admin" + "answer": "Each instance takes 7 minutes, so the gateway is unavailable for 14 minutes.", + "correct": true } ] } diff --git a/apps/academy/src/data/questions/arweave-201/2/quiz-4/Q3.json b/apps/academy/src/data/questions/arweave-201/2/quiz-4/Q3.json index b5e560f6..ae8a7650 100644 --- a/apps/academy/src/data/questions/arweave-201/2/quiz-4/Q3.json +++ b/apps/academy/src/data/questions/arweave-201/2/quiz-4/Q3.json @@ -1,12 +1,15 @@ { - "question": "Should you run an observer for your dev gateway?", + "question": "What does CodeDeploy do on a failed update?", "options": [ { - "answer": "No, they're only for production gateways.", + "answer": "Roll back to the previous version.", "correct": true }, { - "answer": "Yes, they can improve performance." + "answer": "Send you a notification." + }, + { + "answer": "Bribe observers for a better report." } ] } diff --git a/apps/academy/src/data/questions/arweave-201/2/quiz-5/Q1.json b/apps/academy/src/data/questions/arweave-201/2/quiz-5/Q1.json deleted file mode 100644 index b3acbcd9..00000000 --- a/apps/academy/src/data/questions/arweave-201/2/quiz-5/Q1.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "question": "Can multiple gateways reuse data?", - "options": [ - { - "answer": "Yes, but only CHUNKS_DATA_PATH, CONTIGUOUS_DATA_PATH, and HEADERS_DATA_PATH.", - "correct": true - }, - { - "answer": "Yes, but only one gateway should have START_WRITERS.", - "correct": true - }, - { - "answer": "No, all data is unique to a gateway." - } - ] -} diff --git a/apps/academy/src/data/questions/arweave-201/2/quiz-5/Q2.json b/apps/academy/src/data/questions/arweave-201/2/quiz-5/Q2.json deleted file mode 100644 index c3628c87..00000000 --- a/apps/academy/src/data/questions/arweave-201/2/quiz-5/Q2.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "question": "Can you use webhooks without unbundling transactions?", - "options": [ - { - "answer": "Yes, but only for layer 1 transactions and blocks.", - "correct": true - }, - { - "answer": "No, you need to activate it to use webhooks." - }, - { - "answer": "Yes, they will trigger on all transactions." - } - ] -} diff --git a/apps/academy/src/data/quizzes/arweave-201/2.json b/apps/academy/src/data/quizzes/arweave-201/2.json new file mode 100644 index 00000000..7594846c --- /dev/null +++ b/apps/academy/src/data/quizzes/arweave-201/2.json @@ -0,0 +1,154 @@ +{ + "title": "Final Quiz", + "questions": [ + { + "question": "Will your deployment succeed on the first run?", + "options": [ + { + "answer": "No, because AWS can't vaildate the SSL certificates.", + "correct": true + }, + { + "answer": "No, because you didn't assign a cost center." + }, + { + "answer": "No, because SSL certificate validation always times out." + } + ] + }, + + { + "question": "How many DNS records does your gateway need?", + "options": [ + { + "answer": "Two records, one for the domain root of the gateway and a wildcard record is required for sandboxing and ArNS.", + "correct": true + }, + { + "answer": "One for the domain root." + }, + { + "answer": "Three for some DNS providers that require CAA records.", + "correct": true + } + ] + }, + + { + "question": "How can you check your gateway is working?", + "options": [ + { + "answer": "By calling the /ar-io/healthcheck endpoint.", + "correct": true + }, + { + "answer": "By reading the CloudWatch Logs.", + "correct": true + }, + { + "answer": "By calling the /ar-io/status endpoint." + } + ] + }, + { + "question": "Should you use the same key for gateway and observer?", + "options": [ + { + "answer": "No, because the observer key is stored on AWS.", + "correct": true + }, + { + "answer": "No, because that would be too easy." + }, + { + "answer": "Yes, because it saves you the key management hassle." + } + ] + }, + + { + "question": "Can you host your gateway on a subdomain?", + "options": [ + { + "answer": "Yes, you can use a subdomain.", + "correct": true + }, + { + "answer": "No, it has to be a second-level domain." + }, + { + "answer": "No, you must use an ENS domain." + } + ] + }, + + { + "question": "Why does the gateway use two wallet addresses?", + "options": [ + { + "answer": "One key is used to join the AR.IO network.", + "correct": true + }, + { + "answer": "One is used to submit reports to Arweave.", + "correct": true + }, + { + "answer": "You can use the same key for joining the network and submit reports.", + "correct": true + } + ] + }, + { + "question": "Can your gateway work without a domain?", + "options": [ + { + "answer": "Yes, but sandboxing via dynamic subdomains won't be available.", + "correct": true + }, + { + "answer": "Yes, but human-friendly ArNS names won't be available.", + "correct": true + }, + { + "answer": "No, it won't start without an assigned domain.", + "correct": false + } + ] + }, + + { + "question": "Why does this setup include a load balancer?", + "options": [ + { + "answer": "To distribute the load between two EC2 instances.", + "correct": true + }, + { + "answer": "To protect the EC2 instances with a web application firewall.", + "correct": true + }, + { + "answer": "To improve reliability.", + "correct": true + } + ] + }, + + { + "question": "What is the job of CodeDeploy in this setup?", + "options": [ + { + "answer": "It will update the gateway when a new version is released.", + "correct": true + }, + { + "answer": "It will deploy the gateway." + }, + { + "answer": "It will check the health of the deployment." + } + ] + } + ] +} diff --git a/apps/academy/src/pages/tracks/arweave-201/1.mdx b/apps/academy/src/pages/tracks/arweave-201/1.mdx index d79a34fc..e0207d4a 100644 --- a/apps/academy/src/pages/tracks/arweave-201/1.mdx +++ b/apps/academy/src/pages/tracks/arweave-201/1.mdx @@ -63,9 +63,9 @@ The AR.IO gateway is implemented as a Docker Compose application. It consists of Now that you understand our Arweave gateway of choice let’s set one up! - - - + + + ## Installing the Gateway @@ -110,9 +110,9 @@ Setting the `START_WRITERS` variable to `false` prevents the start of the worker The observer and resolver are containers that run alongside your gateway; they aren't needed for most development tasks, so you can deactivate them. - - - + + + ## Testing the Gateway @@ -197,9 +197,9 @@ https://sandbox-id-99999.arweave.local/transaction-id-9999 However, the hosts file doesn’t support wildcard subdomains, so you must manually set every sandbox domain or (which is easier) delete the `ARNS_ROOT_HOST` to deactivate sandboxing again. - - - + + + ## Basic Configuration Options @@ -247,9 +247,9 @@ The observer is an additional container that runs alongside your gateway to chec The resolver is responsible for resolving ArNS names, but you can deactivate it and let your trusted node resolve ArNS names. - - - + + + ## Advanced Configuration Options @@ -350,9 +350,9 @@ Make sure you set the `ADMIN_API_KEY` inside your `.env` file. With the `SIMULATED_REQUEST_FAILURE_RATE` variable that goes from 0 to 1, you can define the probability of request errors. This way, you can check how clients handle a flaky gateway. - - - + + + ## Summary diff --git a/apps/academy/src/pages/tracks/arweave-201/2.mdx b/apps/academy/src/pages/tracks/arweave-201/2.mdx new file mode 100644 index 00000000..f865694f --- /dev/null +++ b/apps/academy/src/pages/tracks/arweave-201/2.mdx @@ -0,0 +1,419 @@ +--- +title: Arweave 201: Lesson 2 +description: This lesson covers installing and running an Arweave gateway on AWS. You will deploy the cloud infrastructure using Terraform. This lesson will also explain how to update the gateway via CodeDeploy. +icons: ["arweave", "fundamentals"] +--- + +import LessonLayout from "../../../components/LessonLayout"; +import Callout from "../../../components/mdx/Callout"; +import QuizStatusChecker from "../../../components/mdx/QuizStatusChecker"; +import Question from "../../../components/mdx/Question"; +import LessonQuestionsModal from "../../../components/mdx/LessonQuestionsModal"; +import LessonInformationalModal from "../../../components/mdx/LessonInformationalModal"; + + + +## About this Lesson + +Greetings! Welcome to the first cloud lesson of the Arweave 201 track. In the previous lesson, I explained how to run an Arweave gateway on your local machine for development purposes. In this lesson, you will apply that knowledge to the cloud by deploying a gateway to AWS. + +Running your own gateway is useful if your application needs advanced features like webhooks, which let your gateway call external services when specific transactions are submitted to Arweave. With your gateway, you improve everyone's access to data on Arweave and participate in the AR.IO network to earn IO tokens. + +## Prerequisites + +To complete this lesson, you need: + +- **A basic understanding of HTTP, TLS/SSL, DNS, Linux, Docker, and AWS.** +- A **basic understanding of blockchains** (i.e., transactions, wallets) is also helpful. +- You also need a **Linux system with [Terraform](https://developer.hashicorp.com/terraform/install?product_intent=terraform) and Git.** +- A browser with an [Arweave wallet](https://www.arconnect.io/). +- As you will deploy the gateway on AWS, **you need an [AWS account](https://aws.amazon.com/resources/create-account/).** +- A (sub-)**domain** you can assign to your gateway. + + + Note: Running a gateway isn’t free. However, you can destroy the deployment after you complete the + lesson, so you are only billed for a few minutes. + + + + Note 2: The gateway will take at least two weeks to index Arweave transactions. It will be + partially functional before that, but it will relay requests to its trusted node, which impacts + latency. + + +## Why Amazon Web Services? + +AWS is the most popular cloud provider, and while it goes against the spirit of decentralization, most students taking this course will be familiar with AWS. Using IaC definitions written for Terraform, you can rebuild the architecture used in this lesson for any other cloud provider. + +## What Does the Architecture Look Like? + +The deployment consists of multiple AWS resources. Figure 1 illustrates the whole stack. Let’s discuss the purpose of each service. + +- The **DNS provider** ensures that your gateway receives a domain; without it, you can’t use sandboxing or ArNS. +- A **CloudFront distribution** is a content delivery network that can cache HTTP responses, allowing you to serve users globally. Its monthly free tier gives you 1TB of outgoing data and 10 million monthly requests, which can save you some money. +- An **Application Load Balancer** distributes traffic evenly between the EC2 instances, stops serving an instance if it goes down, and comes with a web application firewall that protects your gateways from DDoS attacks. +- An **Auto-Scaling Group** will start two EC2 instances, and CodeDeploy can use it to remove instances from the load balancer when updating. +- **EC2 instances** run the gateway software. +- **Elastic Block Storage** drives store each instance's index and cache files. +- **Elastic File System** allows the instances to share data. +- **SSM Parameter Store** stores encrypted configuration and wallet data the gateways require to join the AR.IO network. +- **CloudWatch** stores all logs created by each gateway’s Docker containers. +- **CodeDeploy** a CI/CD runner that will handle updates to the gateway. +- The **S3 bucket** stores the gateway updates for CodeDeploy. + +![figure-1](/assets/tracks/arweave-201/2/figure-1.png) + +
*Figure 1: AR.IO Gateway on AWS Architecture*
+ + + + + + + +## Deploying the Gateway + +The gateway deployment process consists of five major steps. + +1. Generating wallets for the gateway and the observer +2. Cloning the Git repository with the Terraform definitions +3. Configuring Terraform and the gateway +4. Deploying to AWS +5. Testing the deployment with an API client + +### Generate Arweave Wallets + +If you want to join the AR.IO network, your observer needs two wallet addresses. + +1. An address that identifies the gateway. You will receive IO tokens when your gateway behaves well in the network. This wallet gets the most rewards, but you won’t upload it to AWS. +2. This is the address of the wallet that your observer uses to submit reports to Arweave. This wallet is uploaded to AWS because it needs to submit transactions. However, it doesn’t receive many rewards, so it’s less critical than your gateway wallet. + +You can create these wallets with [ArConnect](https://www.arconnect.io/) and save the observer wallet as a keyfile so you can interact with the AR.IO gateway website via your browser wallet. You only need the address of your gateway key; no export is required. However, you must export a keyfile for the observer key. + +### Cloning the Repository + +You can clone the repository with the following commands: + +```bash +git clone https://github.com/Developer-DAO/ario-gateway-aws.git arweave-gateway +cd arweave-gateway +git checkout arweave-201-track +``` + +After that, you have an `arweave-gateway` directory with all Terraform definitions. + +### Configuring the Deployment + +Next comes the configuration, for which you need to copy the configuration templates with these commands: + +```bash +cd resources +cp template.env.terraform .env.terraform +cp template.env.gateway .env.gateway +``` + +#### Configuring Terraform + +Terraform uses `resources/.env.terraform` at deployment. It contains AWS access tokens and basic configurations for VPCs and regions. + +You need to create an AWS access key to complete the provider token section of the config. + +1. [Go to the AWS IAM console](https://console.aws.amazon.com/iamv2/home#/users) +2. Select one of your users or create a new one +3. Open the Security Credentials tab +4. Scroll down to the Access Keys section +5. Press the Create Access key button +6. Select Command Line Interface +7. Confirm the recommendation +8. Click Next +9. Give the key a name like “Terraform Arweave” +10. Click Next +11. Copy the access key and paste it as `AWS_ACCESS_KEY_ID` value +12. Copy the secret access key and paste it as `AWS_SECRET_ACCESS_KEY` value + +Next is the gateway-related information, such as domains and aliases. + +- `alias` is useful if you have multiple gateway deployments, but right now, just enter `"arweave-201"`. +- `domain_name` and `subdomain_name` are required; enter values for a domain you control. +- `observer_key` is the observer key as JSON/JWK string (without newlines, use single quotes). Terraform will store it encrypted inside the SSM Parameter Store. You get it from the keyfile you exported from ArConnect. + +Finally, we have the AWS configuration, such as region and VPC. + +- `region` is the AWS region you want to use for the deployment. +- account_id is your AWS account ID. +- `vpc_id` is the ID of the VPC you want to use. You will find the ID of your default VPC in the[ AWS VPC console](https://console.aws.amazon.com/vpcconsole/home#vpcs:). +- You need at least two `subnets` in your VPC. For this lesson, the public and private subnets can be the same. You can find them in [the AWS VPC console](https://console.aws.amazon.com/vpcconsole/home#subnets:). +- For the `instance_type`, I recommend at least `t3a.medium`, but machines with NVMe will generally perform a lot better. + +With the Terraform configuration done, you can configure the gateway. + +#### Configuring the Gateway + +Terraform will upload the content of `resources/.env.gateway` into the SSM Parameter Store, and the gateway will fetch it from there at boot time. It’s used to configure the gateway software at runtime. + +- The `ARNS_ROOT_HOST` is the domain that will host your gateway. (e.g., something like `arweave.example.com`) +- Get the `AR_IO_WALLET` and the `OBSERVER_WALLET` addresses from your ArConnect browser extension. + + + + + + + +### Deploying the Terraform State Resources + +Terraform will store your deployment state in S3 and DynamoDB, but you must manually create these resources before the first deployment. + +First, go to [the AWS DynamoDB console](https://console.aws.amazon.com/dynamodbv2/home#dashboard) and create a new table named `ar-io-gateway-terraform-state` with a partition key named `LockID`. + +Then, go to [the AWS S3 console](https://console.aws.amazon.com/s3/buckets), create a new bucket, and add its name to your `main.tf` file under the `backend` section as value for `bucket,` and replace the `region` value with your deployment region. + +```txt +backend "s3" { + region = "us-east-1" + dynamodb_table = "ar-io-gateway-terraform-state" + bucket = "terraform-state-bucket-1234567890" + key = "ar-io-gateway.tfstate" +} +``` + +### Deploying the Gateway + +You can start a deployment after successfully configuring Terraform and the gateway. The repository comes with several scripts that help you with this. + +To initialize the Terraform backend and install all providers, run the following command: + +```bash +scripts/init +``` + +The output should look like this: + +```txt +Initializing the backend... + +Successfully configured the backend "s3"! Terraform will automatically +use this backend unless the backend configuration changes. +Initializing provider plugins... +- Reusing previous version of hashicorp/random from the dependency lock file +- Reusing previous version of hashicorp/aws from the dependency lock file +- Installing hashicorp/random v3.6.1... +- Installed hashicorp/random v3.6.1 (signed by HashiCorp) +- Installing hashicorp/aws v5.46.0... +- Installed hashicorp/aws v5.46.0 (signed by HashiCorp) +Partner and community providers are signed by their developers. +If you'd like to know more about provider signing, you can read about it here: +https://www.terraform.io/docs/cli/plugins/signing.html + +Terraform has been successfully initialized! + +You may now begin working with Terraform. Try running "terraform plan" to see +any changes that are required for your infrastructure. All Terraform commands +should now work. + +If you ever set or change modules or backend configuration for Terraform, +rerun this command to reinitialize your working directory. If you forget, other +commands will detect it and remind you to do so if necessary. +``` + +Next, you create a deployment plan for your first deployment by running this command: + +```bash +scripts/plan +``` + +The output is quite long and will contain all resources, but the last lines should look like this: + +```txt +Plan: 39 to add, 0 to change, 0 to destroy. + +Changes to Outputs: + + CodeDeployBucket = (known after apply) + + GatewayAlias = "arweave-201" + + GatewayUrl = "https://arweave.example.com/" + + LogGroup = "https://us-east-1.console.aws.amazon.com/cloudwatch/home?region=us-east-1#logsV2:log-groups/log-group/ar-io-nodes-arweave-201" + +──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── + +Saved the plan to: ./resources/terraform-plan.bin + +To perform exactly these actions, run the following command to apply: + terraform apply "./resources/terraform-plan.bin" +``` + +Now comes the big moment: **deploying it all to AWS**. + +You can do so with the following command: + +```bash +scripts/apply +``` + +Yet, the first run will take around 10 minutes and fail. + +It fails because you didn’t set the validation domains for the SSL certificates. You couldn’t do this, as AWS tells you the required values after it creates the certificates, hence the required run. But Terraform doesn’t roll back your deployment on a failed run, so the certificates were created and await validation. + +#### Setting Up Domains and SSL Validation + +To validate the certificates, you must open [the AWS Certificate Manager console](https://us-east-1.console.aws.amazon.com/acm/home?region=us-east-1#/certificates/list) and locate the certificate using your gateway domain name. The status should be Pending Validation. Open it to find the `CNAME` record name and value for the validation process. Use them to create a new `CNAME` record on your DNS provider's website. The validation can take up to 10 minutes, depending on your provider. + +After successful validation, run the plan and apply commands again to see the CloudFront distribution domain name in the outputs. You need it to set up the domain records for your gateway. + +```txt +scripts/plan +scripts/apply +``` + +Now, create two records for your gateway: + +1. A `CNAME` record of the form `arweave.example.com` that points to your CloudFront distribution. +2. A `CNAME` wildcard record of the form `*.arweave.example.com` that points to your CloudFront distribution. + + + Note: Some DNS providers (e.g., Vercel) require a `CAA` record with the value `'0 issue + "amazon.com"'` to allow AWS certificates for your domain. + + +### Testing the Gateway + +You can call some endpoints to test whether the gateway is working. Just replace `arweave.example.com` with your gateway domain. + +Getting the basic Gateway info: + +``` +https://arweave.example.com/ +``` + +Running the health check: + +``` +https://arweave.example.com/ar-io/healthcheck +``` + +Getting a website by transaction ID: + +``` +https://arweave.example.com/yRj4a5KMctX_uOmKWCFJIjmY8DeJcusVk6-HzLiM_t8 +``` + +Getting a website by ArNS name: + +``` +https://ardrive.arweave.example.com/ +``` + +You just deployed your first Arweave gateway, so you are now an Arweave node operator! + +**Congratulations!!!!** + +If you want to delete the whole stack from AWS, you can do so with the following command: + +```bash +scripts/destroy +``` + +If you get an error, check the `instances.tf` file for a `prevent_destroy = true` and remove it. + + + + + + + +## Updating the Gateway + +When a new gateway version is released, you must update your servers. The Terraform code includes a CodeDeploy application for this update. CodeDeploy is a CI/CD service that can stop the node on each instance, install the new version, and restart the node again. + +### Preparing a New Revision + +The first step for each update is preparing a revision, which means creating a directory that includes all files for the new version. You can create one by running the following command: + +```bash +scripts/prepare-revision r123 +``` + +This will create a new directory at `revisions/r123` that contains CodeDeploy scripts and your `.env.gateway` file. + +You must download the latest version of the `docker-compose.yaml` from [the official ar-io-node repository](https://github.com/ar-io/ar-io-node) and save it at `revisions/r123/source/docker-compose.yaml`. + +In that file, you need to remove all build commands from the services, as your servers should pull the Docker images instead of building them from the source. + +In the following code, the last two lines are the build command and should be removed: + +```txt +services: + envoy: + image: ghcr.io/ar-io/ar-io-envoy:${ENVOY_IMAGE_TAG:-latest} + build: + context: envoy/ +``` + +Next, check the file for any newly added environment variables and add them to your `revisions/r123/source/.env.gateway` file. + +_Note: You can also use this update mechanism to change your gateway configuration._ + +### Deploying the New Revision + +To deploy your new revision, you must package the new directory into an archive, upload it to an S3 bucket, and create a new deployment for your CodeDeploy app. This is all done for you with the following command: + +```bash +scripts/deploy-revision r123 +``` + +CodeDeploy will do the following steps: + +1. Block traffic to one EC2 instance +2. Stop the gateway service +3. Install the new `docker-compose.yaml` and `.env.gateway` files +4. Start the gateway service +5. Check the health of the service +6. Allow traffic to the EC2 instance + +Then, it will do the same with the second EC2 instance. This procedure takes between 5 and 10 minutes per instance. If something goes wrong, CodeDeploy will roll back to the previous revision. + + + + + + + +## Summary + +In this lesson, you learned how to deploy an Arweave gateway to AWS and everything related to that task, like configuring Terraform and validating SSL certificates. Now, you know how to host your own gateway to improve everyone's access to Permaweb. + + + +## Conclusion + +Hosting an Arweave gateway in the cloud is much more involved than doing so on your machine. You need to think about reliability, content caching, and security. Running a gateway improves all users' access to data on Arweave. When the AR.IO network goes mainnet, you can join it and earn IO tokens for hosting a gateway. + +You might already think it’s not helpful for decentralization if everyone hosts their nodes on AWS, and you’re right! That’s why you will learn how to deploy a gateway with Akash in the next lesson. + +