Welcome to The Hitchhiker’s Guide to PlantUML!

alternate text

Where system diagrams meet system reality

Imagine

Tip

playbutton_index Press play

Imagine being able to

  1. share a model or diagram between all members of the team that they can all understand and contribute to and edit

  2. draw diagrams like below automatically from a text description.

  3. describe a system before you build it, when you’re building it, and as you maintain it into the future - keeping the description and the system current, and in sync.

  4. maintain that text version in a source code repository beside the code for the system it is describing

Imagine having a diagramming tool that

  1. fits with a developer workflow, and developers are comfortable using

  2. enables lightweight just-enough AgileModeling in a way that meets AgileModelingBP

  3. fits with modern practices of Continuous Integration Continuous Delivery - and “everything as code” including diagrams.

Well that’s what PlantUML gives you, and more…

PlantUML Diagram Examples

playbuttonindex3 Blah Blah Blah… play!

This guide walks through creating PlantUML diagrams, including the ones shown here.

Diagram of a Typical Network

@startuml

!define osaPuml https://raw.githubusercontent.com/Crashedmind/PlantUML-opensecurityarchitecture2-icons/master
!include osaPuml/Common.puml
!include osaPuml/User/all.puml
!include osaPuml/Hardware/all.puml
!include osaPuml/Misc/all.puml
!include osaPuml/Server/all.puml
!include osaPuml/Site/all.puml

'. Mary is a Developer in the Product team. She has a Windows 10 PC and an Android phone.
'. Bob is a Manager in the Accounts team. He has Mac and an iPhone.
'. Ivan is an IT guy who looks after the server. 
'. They connect to the network hub, and via a firewall to the Internet.


' Users
together {
osa_user_green_developer(Mary, "Mary", "Product team", "Developer")
osa_user_green_operations(Ivan, "Ivan", "IT Team", "Server Admin")
osa_user_green_business_manager(Bob, "Bob", "Accounts team", "Manager")
}

' Devices
together {
osa_desktop(pc, "192.168.1.10", "Windows 10", "PC")
osa_laptop(mac, "192.168.1.12", "Mac", "Mac")
osa_iPhone(iphone, "Dynamic IP", "iPhone 11", "Phone")
osa_iPhone(android, "Dynamic IP", "Android 10", "Phone")
osa_server(server, "192.168.1.100", "Ubuntu Server 20.04 LTS", "Server")
}


' Network

osa_device_wireless_router(wifiAP, "192.168.1.1", "Network")
osa_hub(hub, "Office hub", "Hub")
osa_firewall(firewall, "51.37.24.103", "Network")
osa_cloud(cloud, "Internet", "Network")


Mary --> pc: source code
Mary --> android: social media

Bob --> mac: financial info
Bob --> iphone: phone calls


Ivan --> server: configuration

iphone --> wifiAP
android --> wifiAP
wifiAP --> hub

server --> hub
mac --> hub
pc --> hub


hub --> firewall

firewall --> cloud

footer %filename() rendered with PlantUML version %version()\nThe Hitchhiker’s Guide to PlantUML
@enduml

This uses the Plantuml Stdlib Open Security Architecture icon set. See Create a Diagram of a Typical Network

Diagram of an AWS Architecture

@startuml
!include <awslib/AWSCommon>
!include <awslib/AWSSimplified.puml>
!include <awslib/Compute/all.puml>
!include <awslib/mobile/all.puml>
!include <awslib/general/all.puml>
!include <awslib/GroupIcons/all.puml>
!include <awslib/Storage/all.puml>
!include <awslib/ManagementAndGovernance/all.puml>
!include <awslib/CustomerEngagement/all.puml>
!include <awslib/MachineLearning/all.puml>
!include <awslib/NetworkingAndContentDelivery/all.puml>
!include <awslib/Database/all.puml>
!include <awslib/ApplicationIntegration/all.puml>





'Compute/General
'Storage/SimpleStorageServiceS3.png
'ApplicationIntegration/SQS.png
'Compute/Lambda.png
'Compute/EC2
'ManagementAndGovernance/CloudWatch.png
'CustomerEngagement/SESEmail.png
'MachineLearning/SageMaker.png
''Mobile/APIGateway.png
'NetworkingAndContentDelivery/APIGateway2.png
'Database/Aurora.png
'ApplicationIntegration/SQSQueue.png


skinparam linetype polyline
' skinparam linetype ortho

'top left section 
'-------------------------------------------------------------
package EC2_Instance {
General(IngestionApp, "Ingestion App", " ")
General(ChunkingApp, "Chunking Orchestration App", " ")
}

SimpleStorageServiceS3(S3Staging, "Amazon S3 Staging Bucket", " ")
SQS(SQSIngest, "Amazon SQS Ingest Queue", " ")

Lambda(LambdaTrigger, "AWS Lambda Trigger Function", " ")

LambdaTrigger -up-> IngestionApp
IngestionApp -up-> SQSIngest
SQSIngest -down-> ChunkingApp
S3Staging <-down-> EC2_Instance

'top right section 
'-------------------------------------------------------------
together {
SQS(SQSLargeFileQueue, "Amazon SQS Large File Queue", " ")
SQS(SQSSmallFileQueue, "Amazon SQS Small File Queue", " ")
SQS(SQSSingleFileQueue, "Amazon SQS Single File Queue", " ")

EC2(LargeFileChunkingAppEC2, "Large File Chunking App on EC2", " ")
Lambda(LambdaSmallFileChunking, "Small File Chunking Lambda", " ")
Lambda(ImageConversionLambdaFunction, "Image Conversion Lambda Function", " ")
}
'todo dashed line boundary
package DLQ {
SQSQueue(DLQ1, "DLQ", " ")
SQSQueue(DLQ2, "DLQ", " ")
SQSQueue(DLQ3, "DLQ", " ")
}

ChunkingApp -right-> SQSLargeFileQueue
ChunkingApp -right-> SQSSmallFileQueue
ChunkingApp -right-> SQSSingleFileQueue

SQSLargeFileQueue -right-> LargeFileChunkingAppEC2
LargeFileChunkingAppEC2 -down-> SQSSmallFileQueue
SQSSmallFileQueue -right-> LambdaSmallFileChunking
LambdaSmallFileChunking -down-> SQSSingleFileQueue
SQSSingleFileQueue -right-> ImageConversionLambdaFunction

'todo dashed line
SQSLargeFileQueue -down-> DLQ1
SQSSmallFileQueue -down-> DLQ2
SQSSingleFileQueue -down-> DLQ3


'bottom right section 
'-------------------------------------------------------------

SimpleStorageServiceS3(S3Images, "Amazon S3 Images Bucket", " ")
EC2(EC2DLQFailsafeApp, "DLQ Failsafe App on EC2", " ")
SQS(SQSConvertedImageQueue, "Amazon SQS Converted Image Queue", " ")
Lambda(LambdaInferenceInvocation, "Inference Invocation Lambda Function", " ")
Aurora(Aurora, "Amazon Aurora", " ")
APIGateway(AmazonAPIGateway, "Amazon API Gateway", "")
SageMaker(AmazonSageMaker, "Amazon SageMaker Endpoint", "")

DLQ1 -down-> EC2DLQFailsafeApp
DLQ2 -down-> EC2DLQFailsafeApp
DLQ3 -down-> EC2DLQFailsafeApp

EC2DLQFailsafeApp -right-> S3Images

ImageConversionLambdaFunction -down-> S3Images
S3Images -down-> SQSConvertedImageQueue
SQSConvertedImageQueue -left-> LambdaInferenceInvocation
LambdaInferenceInvocation -down-> Aurora
LambdaInferenceInvocation <-left-> AmazonAPIGateway
AmazonAPIGateway <-left-> AmazonSageMaker


'bottom left section 
'-------------------------------------------------------------

CloudWatch(CloudWatch, "Amazon Cloudwatch", " ")
SNS(SNS1, "Amazon SNS", "")
SESEmail(SESEmail, "Email Notification", "")

CloudWatch -right-> DLQ
CloudWatch -left-> SNS1
SNS1 -left-> SESEmail

footer %filename() rendered with PlantUML version %version()\nThe Hitchhiker’s Guide to PlantUML
@enduml

This uses the AWSlib icon set. See Create Real Life AWS Diagrams

Diagram of a Kubernetes Architecture

@startuml
footer Kubernetes Plant-UML
scale max 1024 width
skinparam linetype polyline
skinparam nodesep 10
skinparam ranksep 10



' Azure
!define AzurePuml https://raw.githubusercontent.com/RicardoNiepel/Azure-PlantUML/release/2-1/dist

!includeurl AzurePuml/AzureCommon.puml
!includeurl AzurePuml/AzureSimplified.puml

!includeurl AzurePuml/Compute/AzureAppService.puml
!includeurl AzurePuml/Compute/AzureBatch.puml
!includeurl AzurePuml/Containers/AzureContainerRegistry.puml
!includeurl AzurePuml/Containers/AzureKubernetesService.puml
!includeurl AzurePuml/Databases/AzureDatabaseForPostgreSQL.puml
!includeurl AzurePuml/Databases/AzureCosmosDb.puml
!includeurl AzurePuml/Databases/AzureSqlDatabase.puml
!includeurl AzurePuml/DevOps/AzurePipelines.puml
!includeurl AzurePuml/Identity/AzureActiveDirectory.puml
!includeurl AzurePuml/Networking/AzureLoadBalancer.puml
!includeurl AzurePuml/Security/AzureKeyVault.puml
!includeurl AzurePuml/Storage/AzureBlobStorage.puml
!includeurl AzurePuml/Storage/AzureStorage.puml

' Kubernetes
!define KubernetesPuml https://raw.githubusercontent.com/dcasati/kubernetes-PlantUML/master/dist

!includeurl KubernetesPuml/kubernetes_Context.puml
!includeurl KubernetesPuml/kubernetes_Simplified.puml

!includeurl KubernetesPuml/OSS/KubernetesApi.puml
!includeurl KubernetesPuml/OSS/KubernetesIng.puml
!includeurl KubernetesPuml/OSS/KubernetesPod.puml

actor "DevOps" as devopsAlias
collections "Client Apps" as clientalias
collections "Helm Charts" as helmalias

left to right direction

' Azure Components
AzureActiveDirectory(aad, "\nAzure\nActive Directory", "Global")
AzureContainerRegistry(acr, "ACR", "Canada Central")
AzureCosmosDb(cosmos, "\nCosmos DB", "Global")
AzureKeyVault(keyvault, "\nAzure\nKey Vault", "Global")
AzureLoadBalancer(alb, "\nLoad\nBalancer", "Canada Central")
AzureSqlDatabase(sql, "\nExternal\ndata stores", "Canada Central")
AzurePipelines(ado, "CI/CD\nAzure Pipelines", "Global")

' Kubernetes Components
Cluster_Boundary(cluster, "Kubernetes Cluster") {
    KubernetesApi(KubernetesApi, "Kubernetes API", "")
    
    Namespace_Boundary(nsFrontEnd, "Front End") {
        KubernetesIng(ingress, "API Gateway", "")
    }

    Namespace_Boundary(nsBackEnd, "Back End") {
        KubernetesPod(KubernetesBE1, "", "")
        KubernetesPod(KubernetesBE2, "", "")
        KubernetesPod(KubernetesBE3, "", "")
    }

    Namespace_Boundary(nsUtil, "Utiliy Services") {
        KubernetesPod(KubernetesUtil1, "", "")
        KubernetesPod(KubernetesUtil2, "","")
    }
}

Rel(devopsAlias, aad, "AUTH")
Rel(helmalias, KubernetesApi, "helm upgrade")

Rel(aad, keyvault, " ")
Rel(KubernetesApi, aad, "RBAC", "ASYNC")

Rel(clientalias, alb, "HTTP", "ASYNC")
Rel(alb, ingress, "HTTP", "ASYNC")

Rel(ingress, KubernetesBE1, " ")
Rel(KubernetesBE1, KubernetesBE2, " ")
Rel(KubernetesBE1, KubernetesBE3, " ")

Rel(KubernetesBE2, sql, " ")
Rel(KubernetesBE3, keyvault, "Pod Identity")
Rel(KubernetesBE3, cosmos, " ")

Rel(ado, acr, "docker push")
Rel_U(KubernetesApi, acr, "docker pull")
@enduml

This uses the Azure and Kubernetes icon sets. See kubernetes

Diagram of a Global Widget Production System Using C4

@startuml
!include  <C4/C4_Context.puml>
!include <office/Users/user.puml>

LAYOUT_WITH_LEGEND()


title Top level Context diagram for ACME Global Widget Production


Person(AcmeProdOwner, Acme Production Owner , "<$user> \n Responsible for Production of widgets in ACME Production Site" )
Person(3rdProdOwner, 3rdParty Production Owner , "<$user> \n Responsible for Production of widgets in 3rdParty Production Site" )


System_Boundary(Remote, "Remote") {

    System(ProdSystemHost, "Production Host", "Drives widget Production\n Analyses widget Production data to create reports")
    System(Analytics, "Analytics", "Provides data analysis and a dashboard view data - including relevant Production data")
    System(Monitoring, "Monitoring", "Monitors Production Host\nUses AWS Services")
    System_Ext(SupplyChain, "SupplyChain", "Provides parts to make the widgets")
    System_Ext(InventoryTracking, "InventoryTracking", "Customer Reference")
    

}



Enterprise_Boundary(AcmeProd, "ACME Production Site") {

    System(AcmeWorkStation1, "WorkStation1", " Production setup for a group of widgets")    
    System(AcmeWorkStation2, "WorkStation2", " Production setup for a group of widgets")        
    System(AcmeWorkStationN, "WorkStationN", " Production setup for a group of widgets")        

}


Enterprise_Boundary(3rdProd, "3rdParty Production Site") {


    System(3rdWorkStation1, "WorkStation1", " Production setup for a group of widgets")    
    System(3rdWorkStation2, "WorkStation2", " Production setup for a group of widgets")        
    System(3rdWorkStationN, "WorkStationN", " Production setup for a group of widgets")     
}


Rel_U(AcmeWorkStation1, ProdSystemHost, "Sends Production report for widget")
Rel_U(AcmeWorkStation2, ProdSystemHost, "Sends Production report for widget")
Rel_U(AcmeWorkStationN, ProdSystemHost, "Sends Production report for widget")


Rel_U(3rdWorkStation1, ProdSystemHost, "Sends Production report for widget")
Rel_U(3rdWorkStation2, ProdSystemHost, "Sends Production report for widget")
Rel_U(3rdWorkStationN, ProdSystemHost, "Sends Production report for widget")





Rel_D(AcmeProdOwner, ProdSystemHost, "Reviews Acme and 3rdParty site Production reports")
Rel_D(3rdProdOwner, ProdSystemHost, "Reviews 3rdParty site Production reports")


Rel_D(Analytics, ProdSystemHost, "Data Analysis")
Rel_D(SupplyChain, ProdSystemHost, "Parts")
Rel_D(InventoryTracking, ProdSystemHost, "Tracking")
Rel_D(Monitoring, ProdSystemHost, "Monitoring")

footer %filename() rendered with PlantUML version %version()\nThe Hitchhiker’s Guide to PlantUML

@enduml

This uses the C4 Lightweight Software Architecture Description Method. See Using C4 To Architect ACME Global Widget Production