Index


If you create a Role with a RoleName parameter, you must include --capabilities CAPABILITY_NAMED_IAM in the deploy command.

Be careful, lots of examples on the web have CAPABILITY_IAM rather than CAPABILITY_NAMED_IAM

The symptom is:

An error occurred (InsufficientCapabilitiesException) when calling the CreateChangeSet operation: Requires capabilities : [CAPABILITY_NAMED_IAM]

  • create the database, use a strong password because the db will become public, do not make it public yet
  • under Endpoints, find and select the security group
  • add an inbound rule, limit the IP address to home public IP and the port to 5432
  • modify the database setting Public Instance true
  • go back to the security group, under the Related Resources tab
  • select the NetworkInterfaces (resource type)
  • Find the IP adresses section, and Public IPv4 address in that

You should now be able to connect with psql or similar:

psql "host=$PUBLIC_IP_ADDRESS port=5432 dbname=postgres user=postgres password=foo"

Connecting through python is similar:

public_ip_address=1.2.3.4
password = "foo"
conn = None
try:
    conn = psycopg2.connect(
        host=public_ip_address, 
        port=5432, 
        database='postgres', 
        user='postgres', 
        password=password
    )
    cur = conn.cursor()
    cur.execute('SELECT version();')
    print(cur.fetchone()[0])
    cur.close()
except Exception as e:
    print(f"Database error: {e}")
    raise
finally:
    if conn:
        conn.close()

  • Sick Fizz
  • when running cloudformation-deploy

An error occurred (ValidationError) when calling the CreateChangeSet operation: [/Parameters/NotificationBucket] 'null' values are not allowed in templates

means you have not indented your yaml correctly. Copy/paste is the devil with whitespace sensitive formats.

  • an S3/Bucket resource ID exists, but not in your UI

Bucket names are globally unique (because they are accessed via a url through through a globally unique domain). Avoid using Property/BucketName (or Property/FooName) in cloudformation, the system will assign a unique name if one is not specified.

  FooBucket:
    Type: AWS::S3::Bucket
    Properties:
      # nope...
      # BucketName: !Ref FooBucketName
      ...snip...
  • Unable to validate the following destination configurations

Why would you use an explicit bucket name? To break a circular dependency.

This arises when two or more resources depend on each other. Typically this is a notification configuration on an S3 bucket. The lambda has an Invoke permission, which requires the bucket ARN, and the bucket has a Notification configuration which requires the Lambda ARN. Its circular, so you can not use DependsOn.

Construct a bucket with an explicit name, use that name in the Permission. Creating a resource name with a semi-random suffix is possible (see stackoverflow)) but this does not solve the dependency problem.

date | md5sum | cut -c1-6 | (
  read; aws cloudformation deploy --template-file e01.yaml --stack-name test --parameter-overrides BucketName=test-$REPLY --capabilities CAPABILITY_IAM
)

How many time will I forget this? When creating a lambda in localstack, an error that looks like: Error while creating lambda: Docker not available means I have forgotten (again) to map the docker socket in volumes.

services:
  localstack:
    image: localstack/localstack
    ports:
      - 4566:4566
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
  • Pilots of Baalbek: channeling the gods of 70's rock.
  • Waikiki/Howling Bells.
  • The Mess Hall.

Also:

  • Jayler
  • Samantha Fish

sqlite3 doesnt have a builtin UUID function, but all thats needed is a randomish blob. For example:

external_id text default (hex(randomblob(16)))

Since this might be used as a search field, it should be indexed:

drop table if exists Foo;
drop index if exists foo_xid;

create table Foo (
external_id text default (hex(randomblob(16)))
);

create index foo_xid on Foo (
	xid
);

Benchmarking shows this has good performance. For one million records, using sql and a command line like:

time sqlite3 benchmark.db < 01-test.sql > /dev/null

testing with sql like:

select 1
from
  Foo f
  join Bing b on f.id = b.id;
;

Times reported by time:

join on real user sys
integer primary key 0m2.325s 0m1.209s 0m1.116s
unindexed 16 bytes of text 0m8.290s 0m4.331s 0m3.957s
indexed 16 bytes of text 0m0.547s 0m0.514s 0m0.033s

These numbers are consistent across several runs. Note the indexed text has surprising results.
Its consistently several times faster than an integer field. I can see this becomming a rabbit hole.

See sqlite3 randomblob

I use lighttpd, which is not directly supported by Certbot.

To renew:

  • stop the web service
  • run certbot certonly --standalone
  • restart the web service

certbot has the usual python dependencies that might have to be installed first.

certbot runs a timer to renew certificates automatically, but this has not worked for me twice now.

See:

systemctl status certbot.timer

Somewhere between version 3.40.1 2022-12-28 14:03:47 and 3.46.1 2024-08-13 09:16:08, sqlite3 gained the ability to provide a subsecond 'now'.

select datetime('now', 'subsec'); works as expected in 3.46.1, but not in 3.40.1. Unfortunately the version on DigitalOcean is the older one, instead use:

select strftime('%Y-%m-%d %H:%M:%f', 'now');

For example:

create table Foo (
  id integer primary key,
  created datetime default (strftime('%y-%m-%d %h:%m:%f', 'now'))
);

See DigitalOcean

The example code has a random number as the session secret key:

SECRET_KEY=secrets.token_urlsafe(32)

This doesnt work in gunicorn if there are several workers because each worker gets a separate key.

See the gunicorn home page.