<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Anand k</title>
    <description>The latest articles on Forem by Anand k (@alpha-anand).</description>
    <link>https://forem.com/alpha-anand</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3803647%2F75a0bd3d-78ce-4fef-905e-e47431952d49.jpg</url>
      <title>Forem: Anand k</title>
      <link>https://forem.com/alpha-anand</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/alpha-anand"/>
    <language>en</language>
    <item>
      <title>How I Deployed a Live Blockchain Node (ARC) on AWS EC2 - A Complete Step-by-Step Guide</title>
      <dc:creator>Anand k</dc:creator>
      <pubDate>Sun, 03 May 2026 04:09:31 +0000</pubDate>
      <link>https://forem.com/alpha-anand/how-i-deployed-a-live-blockchain-node-arcon-aws-ec2-a-complete-step-by-step-guide-4nk7</link>
      <guid>https://forem.com/alpha-anand/how-i-deployed-a-live-blockchain-node-arcon-aws-ec2-a-complete-step-by-step-guide-4nk7</guid>
      <description>&lt;h1&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;This article documents a complete, real-world deployment of an Arc blockchain node on AWS EC2. Unlike tutorials that show only the happy path, this guide captures every error encountered, explains why it happened, and shows exactly how it was fixed.&lt;br&gt;
By the end of this guide you will have a fully operational blockchain node with 5 validators, a block explorer, and a complete monitoring stack running on AWS.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Architecture Overview&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;The full stack consists of the following components running in Docker containers on a single EC2 instance:&lt;br&gt;
Arc Consensus Node (arc_consensus) = 5 validator nodes + 1 full node&lt;br&gt;
Arc Execution Node (arc_execution) = EVM-compatible execution layer&lt;br&gt;
Blockscout = blockchain explorer with PostgreSQL database&lt;br&gt;
Nginx = reverse proxy routing traffic to Blockscout&lt;br&gt;
Prometheus = metrics collection from all services&lt;br&gt;
Grafana = visualization and dashboards&lt;br&gt;
cAdvisor + Node Exporter = container and system metrics&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 1: Setting Up the AWS EC2 Instance
&lt;/h2&gt;

&lt;p&gt;1.1 Choosing the Right Instance Type&lt;/p&gt;

&lt;p&gt;Building and running a blockchain node is resource-intensive. The wrong instance size will cause build failures or poor performance. The recommended configuration is:&lt;br&gt;
Instance Type = t3.xlarge or better (Rust compilation needs 4+ vCPUs)&lt;br&gt;
vCPUs   4     = Parallel Docker builds&lt;br&gt;
RAM 16 GB = Multiple containers + DB&lt;br&gt;
Storage (EBS) = 100 GB SSD (gp3) (Docker images + chain data)&lt;br&gt;
OS        = Ubuntu 22.04 LTS&lt;/p&gt;

&lt;p&gt;Important = Using a t3.medium (2 vCPU, 4GB) will cause the Rust compilation to run out of memory and fail after 30-60 minutes.&lt;/p&gt;

&lt;p&gt;1.2 Configuring Security Group Inbound Rules&lt;/p&gt;

&lt;p&gt;After launching the instance, configure the Security Group to allow external access to required ports:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvbau7eagbvfx5vy2w6p2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvbau7eagbvfx5vy2w6p2.png" alt=" " width="691" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Important = Opening only port 80 is not enough. Grafana (3000) and Prometheus (9090) need their own inbound rules.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 2: Installing Required Tools
&lt;/h2&gt;

&lt;p&gt;2.1 Connect to Your EC2 Instance&lt;/p&gt;

&lt;p&gt;ssh -i your-key.pem ubuntu@your-ec2-public-ip&lt;/p&gt;

&lt;p&gt;2.2 Clone the Arc Node Repository&lt;/p&gt;

&lt;p&gt;cd ~&lt;br&gt;
git clone &lt;a href="https://github.com/circlefin/arc-node" rel="noopener noreferrer"&gt;https://github.com/circlefin/arc-node&lt;/a&gt;&lt;br&gt;
cd arc-node&lt;br&gt;
git submodule update --init --recursive&lt;/p&gt;

&lt;p&gt;Important - The submodule step may take several minutes. Do not interrupt it.&lt;/p&gt;

&lt;p&gt;2.3 Install System Dependencies&lt;/p&gt;

&lt;p&gt;sudo apt-get update&lt;br&gt;
sudo apt install docker.io make nodejs npm libclang-dev -y&lt;br&gt;
sudo service docker start&lt;br&gt;
sudo usermod -aG docker $USER&lt;br&gt;
Note - After adding yourself to the docker group, fully close and reopen the terminal for the change to take effect.&lt;/p&gt;

&lt;p&gt;2.4 Install Node.js 22&lt;/p&gt;

&lt;p&gt;The system Node.js version is outdated. Version 22 is required:&lt;br&gt;
sudo npm install -g n&lt;br&gt;
sudo n 22&lt;br&gt;
hash -r&lt;/p&gt;

&lt;p&gt;2.5 Install Foundry&lt;/p&gt;

&lt;p&gt;curl -L &lt;a href="https://foundry.paradigm.xyz" rel="noopener noreferrer"&gt;https://foundry.paradigm.xyz&lt;/a&gt; | bash&lt;br&gt;
source ~/.bashrc&lt;br&gt;
foundryup -i v1.4.4&lt;/p&gt;

&lt;p&gt;Note - If foundryup is not found after source ~/.bashrc, fully close and reopen the terminal, cd back into arc-node, and run foundryup -i v1.4.4 again.&lt;/p&gt;

&lt;p&gt;2.6 Update Docker Compose&lt;/p&gt;

&lt;p&gt;The system Docker Compose version is incompatible with Arc node. Install v2.24.0 manually:&lt;br&gt;
sudo mkdir -p /usr/local/lib/docker/cli-plugins&lt;br&gt;
sudo curl -SL &lt;a href="https://github.com/docker/compose/releases/download/v2.24.0/docker-compose-linux-x86_64" rel="noopener noreferrer"&gt;https://github.com/docker/compose/releases/download/v2.24.0/docker-compose-linux-x86_64&lt;/a&gt; -o /usr/local/lib/docker/cli-plugins/docker-compose&lt;br&gt;
sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose&lt;/p&gt;

&lt;p&gt;2.7 Install Rust&lt;/p&gt;

&lt;p&gt;curl --proto '=https' --tlsv1.2 -sSf &lt;a href="https://sh.rustup.rs" rel="noopener noreferrer"&gt;https://sh.rustup.rs&lt;/a&gt; | sh&lt;br&gt;
When prompted, type 1 and press Enter to proceed with the default installation.&lt;br&gt;
source $HOME/.cargo/env&lt;/p&gt;

&lt;p&gt;2.8 Install npm Dependencies&lt;/p&gt;

&lt;p&gt;cd ~/arc-node&lt;br&gt;
npm install&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 3: Starting the Node
&lt;/h2&gt;

&lt;p&gt;3.1 Run make testnet&lt;/p&gt;

&lt;p&gt;cd ~/arc-node&lt;br&gt;
make testnet&lt;br&gt;
On the first run, Arc compiles its Rust source code inside Docker. This takes 60 - 180 minutes. The system will be under heavy load. This is completely normal (do not interrupt the process).&lt;/p&gt;

&lt;p&gt;Note : If the build fails partway through, run make testnet again. Docker caches completed layers so it will resume from where it left off.&lt;/p&gt;

&lt;p&gt;3.2 Verify the Node is Running&lt;/p&gt;

&lt;p&gt;docker ps&lt;br&gt;
You should see the following containers running:&lt;br&gt;
• validator1_cl, validator2_cl, validator3_cl, validator4_cl, validator5_cl&lt;br&gt;
• validator1_el, validator2_el, validator3_el, validator4_el, validator5_el&lt;br&gt;
• full1_cl, full1_el&lt;br&gt;
• blockscout-backend, blockscout-frontend, blockscout-proxy&lt;br&gt;
• blockscout-db&lt;/p&gt;

&lt;p&gt;3.3 Start the Monitoring Stack&lt;/p&gt;

&lt;p&gt;Grafana and Prometheus are in a separate compose file and must be started independently:&lt;br&gt;
docker compose -f /home/ubuntu/arc/arc-node/.quake/monitoring/compose.yaml up -d&lt;/p&gt;

&lt;p&gt;Important - The monitoring stack is not included in make testnet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 4: Configuration Changes Made
&lt;/h2&gt;

&lt;p&gt;4.1 blockscout.yaml = Frontend API Host&lt;/p&gt;

&lt;p&gt;File: arc-node/deployments/blockscout.yaml&lt;br&gt;
Before (broken on remote servers)&lt;br&gt;
NEXT_PUBLIC_API_HOST: localhost&lt;br&gt;
NEXT_PUBLIC_APP_HOST: localhost&lt;/p&gt;

&lt;p&gt;After&lt;br&gt;
NEXT_PUBLIC_API_HOST: &lt;br&gt;
NEXT_PUBLIC_APP_HOST: &lt;/p&gt;

&lt;p&gt;4.2 compose.yaml = Network Configuration&lt;/p&gt;

&lt;p&gt;File: arc-node/.quake/localdev/compose.yaml&lt;br&gt;
Before&lt;br&gt;
blockscout:&lt;br&gt;
  driver: bridge&lt;br&gt;
  internal: true   # blocks backend from reaching chain RPC&lt;/p&gt;

&lt;p&gt;After&lt;br&gt;
blockscout:&lt;br&gt;
  driver: bridge&lt;br&gt;
  internal: false&lt;/p&gt;

&lt;p&gt;4.3 monitoring/compose.yaml = Grafana User and Ports&lt;/p&gt;

&lt;p&gt;File: arc-node/.quake/monitoring/compose.yaml&lt;br&gt;
Before&lt;br&gt;
user: '501'&lt;br&gt;
ports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;127.0.0.1:3000:3000&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After&lt;br&gt;
user: '472'&lt;br&gt;
ports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;0.0.0.0:3000:3000&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;4.4 prometheus.yml = Correct Scrape Targets&lt;/p&gt;

&lt;p&gt;scrape_configs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;job_name: 'validators'
static_configs:

&lt;ul&gt;
&lt;li&gt;targets:

&lt;ul&gt;
&lt;li&gt;'host.docker.internal:9101'&lt;/li&gt;
&lt;li&gt;'host.docker.internal:9201'&lt;/li&gt;
&lt;li&gt;'host.docker.internal:9301'&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Part 5: Final Working State
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fos399uw0r0dlfkrsbq2u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fos399uw0r0dlfkrsbq2u.png" alt=" " width="681" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Part 6: Load Testing the Node
&lt;/h2&gt;

&lt;p&gt;With the node fully running, test it by sending real transactions:&lt;/p&gt;

&lt;p&gt;make testnet-load RATE=10 TIME=30&lt;/p&gt;

&lt;p&gt;This sends 10 transactions per second for 30 seconds, a total of 300 transactions across all 5 validators. The output confirms successful transaction delivery:&lt;br&gt;
30.067s: Total sent  303 txs (35752 bytes), 10.1 tx/s&lt;/p&gt;

&lt;p&gt;After running the load test, refresh the Blockscout explorer at http:/// to see the transactions appear in real time.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Docker
&lt;/h2&gt;

&lt;p&gt;1) Bind mount host paths must exist before docker compose up so Docker does not create them&lt;br&gt;
2) Container-to-container communication uses internal ports, not host-mapped ports&lt;br&gt;
3) internal: true on a network isolates ALL external access including inter-service calls&lt;br&gt;
4) Each service runs as a specific UID so always chown data directories to match&lt;/p&gt;

&lt;h2&gt;
  
  
  Networking
&lt;/h2&gt;

&lt;p&gt;1) Frontend environment variables like NEXT_PUBLIC_API_HOST are resolved by the browser, not the server&lt;br&gt;
2) Always use the public IP for any variable that the browser reads&lt;br&gt;
3) Opening port 80 in a Security Group does NOT open 3000 or 9090 so each needs its own rule&lt;/p&gt;

&lt;h2&gt;
  
  
  Debugging
&lt;/h2&gt;

&lt;p&gt;1) Read docker logs carefully - every crash has an exact error message&lt;br&gt;
2) Port scan with curl to find actual metrics endpoints instead of guessing&lt;br&gt;
3) Use docker exec ss -tlnp to see what a container is actually listening on&lt;br&gt;
4) A cascade failure (many errors at once) usually has one root cause so find the first error&lt;/p&gt;

</description>
      <category>devops</category>
      <category>blockchain</category>
      <category>node</category>
      <category>aws</category>
    </item>
    <item>
      <title>Kubernetes Troubleshooting Guide: Real-Time Scenarios &amp; Solutions</title>
      <dc:creator>Anand k</dc:creator>
      <pubDate>Tue, 24 Mar 2026 06:59:17 +0000</pubDate>
      <link>https://forem.com/alpha-anand/kubernetes-troubleshooting-guide-real-time-scenarios-solutions-lok</link>
      <guid>https://forem.com/alpha-anand/kubernetes-troubleshooting-guide-real-time-scenarios-solutions-lok</guid>
      <description>&lt;p&gt;Kubernetes is powerful, but with that power comes complexity. In real-world DevOps environments, issues like pod failures, scheduling problems, and resource mismanagement are common. Understanding how to troubleshoot these effectively is what separates a beginner from a skilled DevOps engineer.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ImagePullBackOff Issue&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One of the most common errors in Kubernetes is ImagePullBackOff, which occurs when a container image cannot be pulled.&lt;/p&gt;

&lt;p&gt;Causes:&lt;br&gt;
Invalid or non-existent image&lt;br&gt;
Private repository without authentication&lt;br&gt;
Solution:&lt;/p&gt;

&lt;p&gt;For private images, use ImagePullSecrets:&lt;/p&gt;

&lt;p&gt;kubectl create secret docker-registry demo &lt;br&gt;
  --docker-server=your-registry-server &lt;br&gt;
  --docker-username=your-name &lt;br&gt;
  --docker-password=your-password &lt;br&gt;
  --docker-email=your-email&lt;/p&gt;

&lt;p&gt;Then reference it in your deployment:&lt;br&gt;
spec:&lt;br&gt;
  imagePullSecrets:&lt;br&gt;
    - name: demo&lt;br&gt;
For AWS ECR:&lt;br&gt;
kubectl create secret docker-registry ecr-secret &lt;br&gt;
  --docker-server=${AWS_ACCOUNT}.dkr.ecr.${AWS_REGION}.amazonaws.com &lt;br&gt;
  --docker-username=AWS &lt;br&gt;
  --docker-password=$(aws ecr get-login-password) &lt;br&gt;
  --namespace=default&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;CrashLoopBackOff&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This error indicates that a container is repeatedly crashing and restarting.&lt;/p&gt;

&lt;p&gt;Common Reasons:&lt;br&gt;
Misconfigurations (env variables, volumes)&lt;br&gt;
Incorrect commands in Dockerfile&lt;br&gt;
Application bugs&lt;br&gt;
Liveness probe failures&lt;br&gt;
Insufficient CPU or memory&lt;/p&gt;

&lt;p&gt;How It Works:&lt;br&gt;
Kubernetes restarts the container with increasing delay:&lt;/p&gt;

&lt;p&gt;First retry: ~10 seconds&lt;br&gt;
Next retry: ~60 seconds&lt;br&gt;
This is called backoff strategy.&lt;/p&gt;

&lt;p&gt;Fix:&lt;br&gt;
Check logs: kubectl logs &lt;br&gt;
Describe pod: kubectl describe pod &lt;br&gt;
Validate configs and probes&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Liveness &amp;amp; Readiness Probes&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Kubernetes uses probes to monitor application health.&lt;br&gt;
Types:&lt;br&gt;
Liveness Probe → Restarts container if unhealthy&lt;br&gt;
Readiness Probe → Controls traffic routing&lt;/p&gt;

&lt;p&gt;Misconfigured probes can cause continuous restarts → CrashLoopBackOff.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Resource Management (Critical in Real-Time)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In shared clusters, improper resource usage can affect all applications.&lt;br&gt;
Problem:&lt;br&gt;
One application consumes excessive CPU/memory → others fail&lt;br&gt;
Solutions:&lt;br&gt;
1) Resource Quota (Namespace Level)&lt;br&gt;
Limits total resources a namespace can use&lt;br&gt;
2) Resource Limits (Pod Level)&lt;br&gt;
Restricts individual pod usage&lt;/p&gt;

&lt;p&gt;Important Rule:&lt;br&gt;
Never blindly increase resources. Always identify the root cause and allocate the correct usage.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pod Not Schedulable&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If a pod is stuck in Pending, it means the scheduler cannot place it on any node.&lt;/p&gt;

&lt;p&gt;Debug:&lt;br&gt;
kubectl describe pod &lt;br&gt;
Common Causes &amp;amp; Fixes:&lt;/p&gt;

&lt;p&gt;1) Node Selector: Forces pod to run on a specific node&lt;/p&gt;

&lt;p&gt;nodeSelector:&lt;br&gt;
  node-name: arm-worker&lt;/p&gt;

&lt;p&gt;If label doesn’t match → pod won’t schedule&lt;br&gt;
Fix:&lt;br&gt;
kubectl edit node &lt;/p&gt;

&lt;p&gt;2) Node Affinity: More flexible than nodeSelector:&lt;/p&gt;

&lt;p&gt;Required → Must match&lt;br&gt;
Preferred → Try to match, else fallback&lt;/p&gt;

&lt;p&gt;3) Taints: Prevents pods from scheduling on nodes.&lt;br&gt;
Types:&lt;br&gt;
NoSchedule&lt;br&gt;
NoExecute&lt;br&gt;
PreferNoSchedule&lt;/p&gt;

&lt;p&gt;kubectl taint nodes nodename key=value:NoSchedule&lt;/p&gt;

&lt;p&gt;4) Tolerations: Allows specific pods to run on tainted nodes.&lt;/p&gt;

&lt;p&gt;6.StatefulSet &amp;amp; Persistent Volume Issues&lt;/p&gt;

&lt;p&gt;Stateful applications depend on storage.&lt;/p&gt;

&lt;p&gt;Problem:&lt;br&gt;
Pods stuck in Pending due to missing Persistent Volume (PV)&lt;/p&gt;

&lt;p&gt;Root Cause:&lt;br&gt;
Incorrect StorageClass&lt;/p&gt;

&lt;p&gt;Example issue:&lt;br&gt;
storageClassName: ebs&lt;/p&gt;

&lt;p&gt;This works in AWS but fails in other environments.&lt;/p&gt;

&lt;p&gt;Solution&lt;br&gt;
storageClassName: standard&lt;br&gt;
Debug:&lt;br&gt;
kubectl get storageclass&lt;br&gt;
kubectl describe pod &lt;/p&gt;

&lt;p&gt;Note:&lt;/p&gt;

&lt;p&gt;Delete old PVC before reapplying:&lt;br&gt;
kubectl delete pvc &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;OOMKilled (Out Of Memory)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Occurs when a container exceeds memory limits.&lt;/p&gt;

&lt;p&gt;Causes:&lt;br&gt;
Low memory limits&lt;br&gt;
Memory leaks in application&lt;/p&gt;

&lt;p&gt;Debug:&lt;br&gt;
Check pod events&lt;br&gt;
For Java apps:&lt;br&gt;
Thread dump → kill -3&lt;br&gt;
Heap dump → jstack&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;If app needs 2GB but limit is 200MB → crash is inevitable&lt;/p&gt;

&lt;p&gt;Kubernetes troubleshooting is not about memorizing commands, it’s about understanding system behavior.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>containers</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
