In Part 1 and Part 2, the WordPress workload was deployed using Score with Docker Compose and Kubernetes, respectively. These flows were fast, local, and environment-aware — but they still required container orchestration, YAML generation, and platform ownership.
In this final part, the focus shifts toward a more mature platform engineering model: Deploying same Score-defined workload to a Kubernetes-based Internal Developer Platform (IDP) powered by Humanitec.
This model allows platform engineers to fully abstract operational complexity while delivering secure, scalable infrastructure as a service to developers — automatically.
The outcome:
score.yaml
, deploy it with a single command, and get running apps.humctl score deploy
humctl score deploy
.Before deploying to Humanitec, ensure the following:
humctl
installed and authenticated against the org5min-local
) is availableTo get the example project:
$ git clone https://github.com/victor-ikeme/awesome-score-spec-examples
$ cd awesome-score-spec-examples/examples/wordpress-mysql
To quickly deploy using the Makefile:
$ make score-deploy
After deployment:
$ open http://localhost:8080
To clean up:
$ make score-down
This step is unchanged from previous parts of the series.
From the developer’s perspective, the workload remains completely declarative. The score.yaml
defines the container, service ports, and required resources — with no knowledge of the underlying platform.
apiVersion: score.dev/v1b1
metadata:
name: wordpress
containers:
wordpress:
image: wordpress:latest
variables:
WORDPRESS_DB_HOST: ${resources.db.host}
WORDPRESS_DB_USER: ${resources.db.username}
WORDPRESS_DB_PASSWORD: ${resources.db.password}
WORDPRESS_DB_NAME: ${resources.db.name}
service:
ports:
tcp:
port: 8080
targetPort: 80
resources:
db:
type: mysql
This single spec works across Docker Compose, Kubernetes, and Humanitec. It focuses solely on what the application needs — without dictating how that infrastructure gets delivered.
wp
.Platform Engineers build golden paths by exposing reusable, abstracted infrastructure — not by giving developers YAML or shell scripts. In Humanitec, this means defining resource classes and matching criteria that allow workloads to consume infrastructure safely and predictably.
In this step, simulate the Platform Engineer experience by making a managed MySQL resource available under a custom class called wp
.
We will walk through:
mysql
resource class (wp
)🧠 This pattern allows developers to say “I need a
mysql
” — while the platform decides how to provision it.
First, initialize the Humanitec application and environment.
This guide assumes you’re using 5min IDP, a Kubernetes-based platform setup provided by Humanitec. It also works the same way with other cloud-connected Kubernetes clusters (AWS, GCP, Azure, OpenShift, etc.).
Begin by exporting the following variables:
$ export APP_ID=wordpress-demo
$ export ENV_ID=5min-local
Now, create the application and environment:
$ humctl api post /orgs/${HUMANITEC_ORG}/apps \
-d '{
"id": "'${APP_ID}'",
"name": "'${APP_ID}'",
"env": {
"id": "'${ENV_ID}'",
"name": "'${ENV_ID}'",
"type": "5min-local"
}
}'
If successful, this call registers wordpress-demo
with a 5min-local
environment in your org.
You can also confirm this in the Humanitec Developer Portal:
5min-local
wp
Resource Class.To offer multiple flavors of a resource type (e.g., local MySQL vs. cloud-managed MySQL), define a resource class.
Run the following to create a wp
class for mysql
:
$ humctl api post "/orgs/${HUMANITEC_ORG}/resources/types/mysql/classes" \
-d '{
"id": "wp",
"description": "MySQL database settings for WordPress workloads"
}'
This adds wp
as a valid resource class for MySQL — enabling developers to request it explicitly in Score specs.
The response will confirm the creation:
{
"id": "wp",
"description": "MySQL database settings for WordPress workloads",
...
}
Now, define how to provision MySQL for the wp
class — in this case, using an in-cluster Deployment.
Clone the resource pack repository:
$ git clone https://github.com/humanitec-architecture/resource-packs-in-cluster
$ cd resource-packs-in-cluster/examples/mysql
Initialize and apply the Terraform configuration to create the resource definition:
$ terraform init
$ terraform plan
$ terraform apply
This registers a new resource definition in Humanitec (e.g., hum-rp-mysql-ex-mysql
) that provisions MySQL using native Kubernetes manifests.
🔧 Make sure
humctl login
has already been run before applying Terraform.
Once applied, verify in the Humanitec Portal under Resource Definitions:
wp
Class.Now associate the resource definition with the wp
class in the 5min-local
environment.
First, identify your resource definition ID (e.g., hum-rp-mysql-ex-mysql
), then run:
$ humctl api PUT \
/orgs/${HUMANITEC_ORG}/resources/defs/hum-rp-mysql-ex-mysql/criteria \
--data '[{"env_type": "5min-local", "class": "wp"}]'
This ensures that any Score workload requesting:
resources:
db:
type: mysql
class: wp
…will be resolved using this specific resource definition.
The output should confirm the criteria were set:
[
{
"class": "wp",
"env_type": "5min-local",
"id": "..."
}
]
From a developer’s perspective, it’s now possible to check which resource types (and classes) are available for the current app and environment.
Navigate back to the workload directory:
$ cd ~/awesome-score-spec-examples/examples/wordpress-mysql
Then run:
$ humctl score available-resource-types
This returns a list like:
MySQL mysql datastore wp MySQL database settings for WordPress workloads
This confirms that the mysql
resource with class wp
is now available for use — cleanly abstracted, reusable, and platform-aligned.
wp
MySQL Class and Add DNS + Route Resources for URL Access.With the wp
MySQL resource and class now available on the platform, the developer’s role is simply to express their intent:
“I need a database, and I want this app to be accessible at a predictable URL.”
This step introduces two new Score resource types: dns
and route
.
dns
and route
needed?In our earlier deployments (Docker Compose and Kubernetes), WordPress was accessed via localhost
and static ports. But in a cloud-native IDP like Humanitec, services typically receive ingress URLs dynamically — and those need to be declared explicitly.
dns
resource requests a DNS host to represent the application.route
resource defines how traffic should flow from that DNS to the container (port, path, etc.).Together, these resources enable URL-based access to the app, managed and provisioned by the platform.
The updated score.yaml
reflects the new MySQL class and ingress configuration:
apiVersion: score.dev/v1b1
metadata:
name: wordpress
containers:
wordpress:
image: wordpress:latest
variables:
WORDPRESS_DB_HOST: ${resources.db.host}
WORDPRESS_DB_USER: ${resources.db.username}
WORDPRESS_DB_PASSWORD: ${resources.db.password}
WORDPRESS_DB_NAME: ${resources.db.name}
service:
ports:
tcp:
port: 80
targetPort: 80
resources:
db:
type: mysql
class: wp
dns:
type: dns
route:
type: route
host: ${resources.dns.host}
path: /
port: 80
type: mysql
with class: wp
ensures the app uses the MySQL resource provisioned earlier.dns
and route
request platform-managed ingress, allowing access via an external URL.kubectl port-forward
, and no ingress.yaml
.💡 This is a key moment in our platform-as-a-product journey: developers remain focused on what the app needs — not how the platform satisfies those needs.
To deploy the updated spec, we first define our environment variables for standardization:
$ export HUMANITEC_ENVIRONMENT=5min-local
$ export HUMANITEC_APPLICATION=wordpress-demo
Then we runt the followijg command to deploy our app to our Kubernetes-based IDP powered by Humanitec:
$ humctl score deploy \
-f score/score.yaml \
--app ${HUMANITEC_APPLICATION} \
--env ${HUMANITEC_ENVIRONMENT} \
--wait
This single command triggers the entire orchestration:
No YAML handoffs. No Helm charts. No manual ingress setups.
The infrastructure is fully self-service, declarative, and repeatable — powered by Score and Humanitec.
The final deployment can be inspected from the Humanitec Developer Portal.
The portal provides:
Example output may resemble:
📦 App: wordpress-demo
Environment: 5min-local
🌐 URL: https://wordpress-demo-qax4.localhost
No YAML editing. No Helm charts. No secrets injection logic. Everything flows through Score and Humanitec — seamlessly.
Now, we can go to browser and see our deployed wordpress app using the dns url provisioned bt the humanitec platform:
This final step in the series demonstrates how Score and Humanitec deliver a complete Internal Developer Platform experience:
This approach treats platforms as products, shifting platform engineering from writing automation to designing reliable developer experiences.
Whether deploying locally, to Kubernetes, or across environments with Humanitec, Score enables platform-consistent developer workflows — making self-service infrastructure real.
What began as a WordPress demo now reveals a deeper lesson: A platform is not a set of scripts. It’s a product.
Score allows developers to express intent clearly. Humanitec ensures infrastructure is provisioned reliably. Together, they reduce friction, encourage best practices, and help organizations scale platform maturity — one abstraction at a time.
This tutorial is part of the open-source Awesome Score Spec Examples project.
⭐️ Star the repo to explore more platform-ready workload examples — or contribute your own.
Join me as I talk shop about internal developer platforms, products, tools, tips and everything in between—new episodes every week!