Prepare a Server on AWS
This guide gets an EC2 instance ready for Bring Your Own Server, with its firewall, fixed IP and backup storage. Skysize installs everything else on the server.
Each step has two tabs: click through the Console, or paste from Command line. Your choice applies to the whole page.
Commands run in CloudShell, the terminal icon at the top of the AWS console, so there is nothing to install. Keep the same tab open: each block reuses the values from step 1.
1. Choose your values
Pick the Region closest to your users, and the size for your use.
| Use | Instance type | vCPU | RAM | Disk |
|---|---|---|---|---|
| One production and one staging | m7i.large | 2 | 8 GB | 100 GB |
| Production with staging and development branches | m7i.xlarge | 4 | 16 GB | 200 GB |
Avoid Graviton types such as m7g or t4g: they are ARM, and the installer refuses to run on them. Avoid t3 for production: it runs out of CPU credits under sustained load.
- Console
- Command line
Select your Region at the top right of the AWS console. Use the same one in every step.
export AWS_REGION=us-east-2 AWS_DEFAULT_REGION=us-east-2
NAME=skysize-odoo
TYPE=m7i.large
DISK_GB=100
BUCKET=$NAME-backups-$(aws sts get-caller-identity --query Account --output text)
2. Create the security group
The server needs these inbound rules, and no others:
| Type | Port | Source | Why |
|---|---|---|---|
| HTTP | 80 | Anywhere (0.0.0.0/0) | Certificates and redirects |
| HTTPS | 443 | Anywhere (0.0.0.0/0) | Your Odoo sites |
Skysize itself needs no inbound port. There is no SSH rule because you connect with Session Manager in step 6. Leave PostgreSQL (5432) closed unless you use read-only database access. Keep the default outbound rule, which allows everything: the server needs it.
- Console
- Command line
- Open EC2 → Security Groups → Create security group.
- Set the name and description to
skysize-odoo, and keep the default VPC. - Under Inbound rules, add the two rules above.
- Click Create security group.
VPC_ID=$(aws ec2 describe-vpcs --filters Name=isDefault,Values=true \
--query 'Vpcs[0].VpcId' --output text)
SG_ID=$(aws ec2 create-security-group --group-name "$NAME" \
--description "Skysize Odoo server" --vpc-id "$VPC_ID" \
--query GroupId --output text)
aws ec2 authorize-security-group-ingress --group-id "$SG_ID" \
--protocol tcp --port 80 --cidr 0.0.0.0/0
aws ec2 authorize-security-group-ingress --group-id "$SG_ID" \
--protocol tcp --port 443 --cidr 0.0.0.0/0
If VPC_ID prints None, your account has no default VPC. Set VPC_ID to a VPC with a public subnet, and add --subnet-id in step 4.
3. Create the backup bucket and the server's role
Skysize makes no backups until a project has a backup target. This creates a private bucket and a role that lets the server use it, with no secret to store.
- Console
- Command line
Bucket
- Open S3 → Create bucket.
- Enter a name that is unique across AWS, such as
skysize-odoo-backups-followed by your account ID. - Keep Block all public access on, and click Create bucket.
Role
- Open IAM → Roles → Create role.
- Choose AWS service, then EC2, and click Next.
- Select the policy
AmazonSSMManagedInstanceCore, and click Next. - Name the role
skysize-odoo, and click Create role. - Open the role, then Add permissions → Create inline policy → JSON.
- Paste this, with your bucket's name in place of
YOUR_BUCKET, and name the policybackups:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:ListBucket", "s3:GetBucketLocation"],
"Resource": "arn:aws:s3:::YOUR_BUCKET"
},
{
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:GetObject", "s3:DeleteObject", "s3:AbortMultipartUpload", "s3:ListMultipartUploadParts"],
"Resource": "arn:aws:s3:::YOUR_BUCKET/*"
}
]
}
aws s3 mb "s3://$BUCKET"
cat > ec2-trust.json <<'JSON'
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": { "Service": "ec2.amazonaws.com" },
"Action": "sts:AssumeRole"
}]
}
JSON
cat > backups.json <<JSON
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:ListBucket", "s3:GetBucketLocation"],
"Resource": "arn:aws:s3:::$BUCKET"
},
{
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:GetObject", "s3:DeleteObject", "s3:AbortMultipartUpload", "s3:ListMultipartUploadParts"],
"Resource": "arn:aws:s3:::$BUCKET/*"
}
]
}
JSON
aws iam create-role --role-name "$NAME" \
--assume-role-policy-document file://ec2-trust.json
aws iam put-role-policy --role-name "$NAME" \
--policy-name backups --policy-document file://backups.json
aws iam attach-role-policy --role-name "$NAME" \
--policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
aws iam create-instance-profile --instance-profile-name "$NAME"
aws iam add-role-to-instance-profile \
--instance-profile-name "$NAME" --role-name "$NAME"
sleep 15
The last line gives AWS time to make the new role available.
4. Launch the instance
Use Ubuntu 24.04 for x86. On AWS, use Ubuntu or Debian: Amazon Linux, the image the console offers by default, is not supported and the installer refuses it. The commands here are written for Ubuntu.
- Console
- Command line
Open EC2 → Instances → Launch instances, and set:
| Setting | Value |
|---|---|
| Name | skysize-odoo |
| Application and OS Images | Ubuntu, then Ubuntu Server 24.04 LTS, architecture 64-bit (x86) |
| Instance type | The type from step 1 |
| Key pair | Proceed without a key pair |
| Network settings | Select existing security group: skysize-odoo. Keep Auto-assign public IP enabled. |
| Configure storage | The disk size from step 1, type gp3 |
| Advanced details → IAM instance profile | skysize-odoo |
Then click Launch instance.
INSTANCE_ID=$(aws ec2 run-instances \
--image-id resolve:ssm:/aws/service/canonical/ubuntu/server/24.04/stable/current/amd64/hvm/ebs-gp3/ami-id \
--instance-type "$TYPE" \
--security-group-ids "$SG_ID" \
--iam-instance-profile "Name=$NAME" \
--block-device-mappings "DeviceName=/dev/sda1,Ebs={VolumeSize=$DISK_GB,VolumeType=gp3}" \
--tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=$NAME}]" \
--query 'Instances[0].InstanceId' --output text)
aws ec2 wait instance-running --instance-ids "$INSTANCE_ID"
5. Give it a fixed IP
An instance's public IP changes when it stops and starts, which would break your DNS records. Note this IP: your DNS records will point to it.
- Console
- Command line
- Open EC2 → Elastic IPs → Allocate Elastic IP address, and click Allocate.
- Select the new address, then Actions → Associate Elastic IP address.
- Pick your instance, and click Associate.
ALLOC_ID=$(aws ec2 allocate-address --domain vpc --query AllocationId --output text)
aws ec2 associate-address --instance-id "$INSTANCE_ID" --allocation-id "$ALLOC_ID"
aws ec2 describe-addresses --allocation-ids "$ALLOC_ID" --query 'Addresses[0].PublicIp' --output text
echo "Bucket: $BUCKET Region: $AWS_REGION"
6. Connect to the server
In the EC2 console, select the instance and choose Connect → Session Manager → Connect. This opens a terminal in your browser, with no SSH key or open port. It can take a minute or two to become available after launch. This is where you paste the Skysize install command.
7. Set the backup target
Once your project exists, open its Settings → Backup Target, click Add Target, and fill in:
| Field | Value |
|---|---|
| Type | AWS S3 |
| Bucket | Your bucket's name |
| Region | Your Region, such as us-east-2 |
| Prefix | The project name |
| Authentication | IAM role |
Click Test to check it from your server.
Sending email from Odoo
AWS blocks outgoing port 25 by default. Use an SMTP relay on port 587, such as Amazon SES. See Configure Outgoing Email.
Connect the server to Skysize
Your server is ready. Follow Set Up Your Own Server, starting at the step that registers the server. In short: register it in the dashboard, connect to it over SSH, and paste the install command. The status changes to Online within a minute of the installer finishing.
Once your first project runs, add your domain.
If something goes wrong
The dashboard says ports 80 and 443 are not reachable. Check the firewall rules above, and that the public IP in the server's settings is the one you noted. Then click Check again.
The server stays Offline. The server connects out to Skysize, so no inbound rule fixes this. Run these on the server:
sudo systemctl status skysize-agent
sudo journalctl -u skysize-agent -n 50
nc -zv cp.skysize.io 50051
If the installer did not finish, or the join token was already used, use Regenerate join token on the server's page and run the install command again.
Still stuck? Open Support in the dashboard and include the output of those commands.