SSL ConfigurationUnlike the automatically generated SSL certificates supported by App Engine CDN / Load Balancing requires you to provide your own SSL certificate. If you are using a provider like NameCheap then the first step is to create a key and certificate signing request. Using the Certificate Signing Request you can request a certificate from your SSL provider of choice. After the usual verification of email address you will typically end up with a certificate file. This can then be used by the create certificate resource tool.
1. Create your certificate
openssl genrsa -out my-private-key.key 2048
2. Create your certificate signing request
openssl req -new -key my-priavate-key.key -out certificate-signing-request.csr
Once you have your certificate signing request you will paste it into your SSL provider's site to start the signing process. Once your respective domain validation is done you will be sent your certificate. Save it into my-certificate.cert to continue below.
3. Upload your certificate
gcloud compute ssl-certificates create certificate-name --certificate my-certificate.cert --private-key my-private-key.key
Create your CDN resource
Once you have your SSL certificate imported using the gcloud tool you can go through the setup to create your CDN resource. There are a few configuration options to take into consideration
- When you create a new origin you will need to create a new load balancer for it.
- Backend Confguration: create a new storage bucket. Make sure it is CDN enabled.
- Host path rules: You should configure your custom host and path rules to your host like cdn.yourdomain.com and path /* to match all content.
- Frontend configuration: You will pick the HTTPS protocol, network service tier premium, create a static IP, select the certificate you uploaded above.
Make a note of the IP address of your load balancer once it is created or refer to the address list in your account.
Enabling cache controlThe cache control best practices suggests to update the cache control for your assets.
Whether you are using the user interface or the API to upload your content you may find that you end up with a large number of files where you need to update the cache control. Doing this via the user interface can become tiresome for more than a couple of files.
If you are looking for a quick hack script that will update the cache control settings for every file in your bucket (* not intended for very large buckets) this script could be for you:
Note that I am setting the cache maximum age to 7 days in seconds. This will significantly improve cache performance of static content and can make use of edge caching.#!/usr/bin/bash BUCKET=<your bucket e.g. gs://some-bucket-name> files=$(gsutil ls -r $BUCKET); for i in $files; do if [[ "$i" == *: ]] || [[ "$i" == */ ]]; then echo "Skipping directory $i"; else echo "Updating cache control for $i"; gsutil setmeta -h "cache-control:public, max-age=604800" $i; fi; done;
Set up your ANAME record
For custom domain names you want to serve your content from which you configured above in the CDN resource setup you will now need to create ANAME records with your DNS provider. This step is really dependent upon your provider. Once your DNS has propagated you can now start to reconfigure your site to use the freshly created SSL resources.
Go native with Android
Compat[ibility] is main route
To make things more interesting I will be starting out with an older version of Android (Nougat) and migrating my app to new versions. At the same time I will migrate the app from Java to Kotlin.
In order to make things as real as possible I will be creating an app in a very competitive space (pregnancy tracking) and launching it on the app store. As I go I will share useful resources and guides that I tried to help me.
Migrating to Google App Engine was more straightforward than trying to rebuild my environment and meant I had to change a few things in my setup.
- Unable to update app: Class file is Java 8 but max supported is Java 7: Don't forget Guava, only versions of guava up to 20 are supporting Java 1.7
- The app config version isn't the SDK version, it is like the AWS build version and can't contain '.' periods so version 0 it is.
- Downloading the database is a pain in a server-less environment as AWS only supports binary snapshots. But fear not, a bit of ssh / yum / security group manipulation and the download is done in about 20 minutes.
- Deploy a new SQL instance in the cloud console: Note you need to include the create database or use the advanced options to specify the database to import your SQL to.
- Then hit a brick wall "You can't have any JDBC database with Google App Engine." due to "java.lang.management.ManagementFactory is a restricted class". This is a slight misnomer, it is creating threadpool connection pool resources which is prohibited.
- In steps a non threaded connection pool: http://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html#Plain_Ol'_Java
- More security errors: setProperty.networkaddress.cache.ttl
- Moved to Google SQL driver "com.mysql.jdbc.GoogleDriver"
- ERROR: (gcloud.beta.sql.connect) HTTPError 400: Invalid value for: Invalid format: "2017-02-16T20:01:08+00:00" is malformed at "+00:00"
At the moment one of my side projects which I want to keep alive is Rediscover.Work. It is currently hosted in AWS using Elastic Beanstalk and RDS. This made sense at the time when I was trying to get the site up quickly. Now that the project is no longer funded though it is time to do a bit of belt tightening.
As with any project it is worth looking at different options for how it could be deployed. There were never more than there are now:
* AWS Elastic Beanstalk + RDS. Current running cost of around $96 per month. + Easy install. - Cost.
* AWS Lambda + RDS. + Simple scaling. - Migration costs are prohibitive.
* EC2 Instance: $9.52 according to the price calculator. + Already have needed tools - More admin to manage instance personally.
* Google App Engine and Cloud SQL: $8.01 according to the price calculator. + Ease of mantenance and app engine security scanning. - Migration to app engine layout.
As I already have all the tools needed to create the EC2 Instance solution and it requires the minimum investment in tooling I chose to go down that route first and see how things played out. In part 2 of this blog I will see how hard it is to migrate to app engine as this seems like a better solution for the long term.
- Build dependencies and update dependency versions using
- Package the code into a WAR to be deployed on the new shared EC2 instance.
- Launch a new instance which will run the site and database.
- Start hacking ansible (and loose the will to live due to so many issues with config).
It turns out that planning a wedding is really quite tough so I wanted to share a few tips on what we have learned so far!
- You can buy wedding rings online > (yes those are our rings).
- But, you need to shop for rings in person, our original ring choices were nothing like what we ended up with.
- Check your wedding ring size when your hands are hot and cold, you don't want to end up with a ring you bought in February that you can't fit on when it comes to the big day.
- Everything costs a lot more than you would expect. Make a budget and if you are really good, try to stick to it.
- Start shopping for your wedding dress the day you get engaged, yes it can take that long.
- If you can keep your party small then you can go big on the venue and get somewhere really special.
- Photography can cost a lot more than you think, in London wedding photographers charge around £150 per hour!
- Don't forget while planning and organising for all of your guests that it is still your day.
- Create a checklist of everything you want to get done. Start from high level decisions like:
- Which country will we get married in.
- Are we going for a church or registry office.
- What is the overall budget.
- How many guests will be invited.
- Don't eat for 24 hours before your tasting dinner for the reception so you can manage everything on the menu.
- Find a partner who doesn't want a Hollywood wedding then give her the best day of her life!
Some time ago I had the chance to work wuth a development team which had separate QA resource. The team was working in the standard "over the wall" mentality. Developers do stuff, QA engineers pick it apart and so on.
I heard a phrase which really gave me pause:
"QA is working on behalf of the customer"
This sounds great, the QA engineers really take ownership of thinking about the customer. What does it say about the development team motives? Aren't they thinking about the customer?
In the teams I have helped shape I have always avoided dedicated QA because I suspect it creates an environment where people defer responsibility. On the other hand it might mean that a stretched development team can roll out faster as they can rely on QA to catch the issues. That might sound plausible but in the world of ever accelerating deployment can manual testing really keep up?
One of the great pleasures of my role is to start hiring a technology team. The first role we are trying to recruit for is a 'Full Stack Developer'. We will also be hiring for Android and IOS developers too so watch this space.
We were really lucky to be able to find two really strong candidates who have a wealth of experience. Exciting times!
One of the hardest things to rationalise are random acts. Today I found someone had pushed my motorbike over. Unfortunately there was quite a bit of damage. I still need to strip down the rear fairing which is cracked, but the damage already stands at over £350.
With insurance premiums spiralling and excess now nearly half the value of the bike, maybe it is time to let it go. You just can't keep anything nice.
- Attending conferences and fairs.
- Researching top companies via lists from sites like glassdoor and the guardian top graduate employers lists.
- Through my network trying to identify potential companies.
- Introduction Email.
- Initial Call.
- Send CV.
- On Site Interview(s).
- Proposal Meeting.
- Offer Review.
Uncaught Error: Syntax error, unrecognized expression: [data-'Times New Roman'-dropdown]
Then check out this solution from http://jelaniharris.com/2014/fixing-foundation-5s-unrecognized-expression-syntax-error/
- Unable To Find A Medium Containing A Live File System
- ACPI PPC Probe failed
- React / Go / Mongo : MGR
- React / Node / Mongo: RNM
- Angular / Ruby / Mongo : MRA
- Ruby / Rails / Postgres : RRP
This is a quick blog post FYI in case you are searching for error messages like:
msg: Destination /etc/mysql/my.cnf not writable
JFDI: Hack, Ship, Hope
Ask a Friend
- Searching the internal repos for a working solution (yes code can be re-used).
- Internal forum activity.
- Engaging a more experienced engineer. We all need coffee breaks.
- Finding the coding standard for your team and seeing what the normal design pattern usage is.
The past, like the future, is indefinite and exists only as a spectrum of possibilities. - Stephen HawkingThere can at times simply be too many possible ways to solve a problem. Design patterns can help but they some times contradict each other. In order to be able to 'get things done' some times the best thing can be to have a standard way which means you can get started then discover along the way the problems you still don't know about. This idea works well with the concept of tracer code.