diff --git a/.github/workflows/automatic-doc-checks.yml b/.github/workflows/automatic-doc-checks.yml
new file mode 100644
index 00000000..4de036ce
--- /dev/null
+++ b/.github/workflows/automatic-doc-checks.yml
@@ -0,0 +1,23 @@
+name: Main Documentation Checks
+
+on:
+ push:
+ branches: [main]
+ paths:
+ - 'docs-rtd/**'
+ pull_request:
+ paths:
+ - 'docs-rtd/**'
+ workflow_dispatch:
+ paths:
+ - 'docs-rtd/**'
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ documentation-checks:
+ uses: canonical/documentation-workflows/.github/workflows/documentation-checks.yaml@main
+ with:
+ working-directory: "docs-rtd"
diff --git a/.github/workflows/periodic-style-checks.yml b/.github/workflows/periodic-style-checks.yml
new file mode 100644
index 00000000..a7f0c9bb
--- /dev/null
+++ b/.github/workflows/periodic-style-checks.yml
@@ -0,0 +1,19 @@
+name: Periodic Style Checks
+
+on:
+ schedule:
+ - cron: "0 1 * * 4" # Runs at 01:00 AM on every Wednesday
+
+jobs:
+ vale:
+ name: Style checker
+ runs-on: ubuntu-22.04
+ defaults:
+ run:
+ shell: bash
+ working-directory: "docs-rtd"
+ steps:
+ - uses: actions/checkout@v4
+ - name: Run vale
+ run: |
+ make vale
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
new file mode 100644
index 00000000..227ed058
--- /dev/null
+++ b/.readthedocs.yaml
@@ -0,0 +1,30 @@
+# .readthedocs.yaml
+# Read the Docs configuration file
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+
+# Required
+version: 2
+
+# Set the version of Python and other tools you might need
+build:
+ os: ubuntu-22.04
+ tools:
+ python: "3.11"
+ jobs:
+ pre_install:
+ - git fetch --unshallow || true
+
+# Build documentation in the docs/ directory with Sphinx
+sphinx:
+ builder: dirhtml
+ configuration: docs-rtd/conf.py
+ fail_on_warning: true
+
+# If using Sphinx, optionally build your docs in additional formats such as PDF
+formats:
+ - pdf
+
+# Optionally declare the Python requirements required to build your docs
+python:
+ install:
+ - requirements: docs-rtd/.sphinx/requirements.txt
diff --git a/.wokeignore b/.wokeignore
new file mode 120000
index 00000000..5723276b
--- /dev/null
+++ b/.wokeignore
@@ -0,0 +1 @@
+docs-rtd/.wokeignore
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 92876e94..286a33cb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
## 0.15.0 (October 14, 2024)
NOTES:
+
* **This release requires Juju controller version 2.9.49 or higher juju.**
* **If using JAAS, this release requires Juju controller version 3.5.0 or higher.**
* This release uses juju client api code from the juju 3.5.1 release.
@@ -26,6 +27,7 @@ BUG FIXES:
## 0.14.0 (September 9, 2024)
NOTES:
+
* **This release requires juju controller version 2.9.49 or later juju.**
* This release uses juju client api code from the juju 3.5.1 release.
@@ -44,6 +46,7 @@ BUG FIXES:
## 0.13.0 (July 15, 2024)
NOTES:
+
* **This release requires juju controller version 2.9.49 or later juju.**
* This release uses juju client api code from the juju 3.5.1 release.
@@ -62,12 +65,14 @@ BUG FIXES:
## 0.12.0 (April 22, 2024)
NOTES:
+
* **This release requires juju controller version 2.9.49 or later juju.**
* This release uses juju client api code from the juju 3.5-beta1 candidate release.
* The added JAAS login enhancements requires Juju controller version 3.5.0 or higher.
* The added Juju secrets support requires Juju controller version 3.4.0 or higher.
ENHANCEMENTS:
+
* Support for user secret management is added. You can now use `juju_secret` and `juju_access_secret` resources to create and manage secrets, as well as grant/revoke access to the applications in your plan. You can also use `juju_secret` data source in your configuration to access a secret.
* Provider config is enhanced with support for Client ID and secret to enable logging in to JAAS using client credentials.
@@ -79,6 +84,7 @@ BUG FIXES:
## 0.11.0 (March 18, 2024)
NOTES:
+
* **This release requires juju controller version 2.9.47 or later juju.**
* This release uses juju client api code from the juju 3.3.0 release.
@@ -93,6 +99,7 @@ ENHANCEMENTS:
applications. This is similar to `juju deploy --bind` and `juju bind` commands.
BUG FIXES:
+
* Fix upgrade charm revision for application resources by @hmlanigan in https://github.com/juju/terraform-provider-juju/pull/414
* Fixes Config/Revision update ordering. by @anvial in https://github.com/juju/terraform-provider-juju/pull/407
* Adds error check to ReadModel function by @anvial in https://github.com/juju/terraform-provider-juju/pull/416
diff --git a/README.md b/README.md
index 2a065c5c..84e136a5 100644
--- a/README.md
+++ b/README.md
@@ -74,12 +74,14 @@ export TF_LOG_PROVIDER=TRACE ; export TF_LOG_PATH=./terraform.log
Run your terraform commands.
To find logs specific to the juju provider code:
+
```shell
grep "@module=juju.resource" ./terraform.log
grep "@module=juju.datasource" ./terraform.log
```
To find logs specific to the juju client talking to juju itself:
+
```shell
grep "@module=juju.client" ./terraform.log
-```
\ No newline at end of file
+```
diff --git a/docs-rtd/.custom_wordlist.txt b/docs-rtd/.custom_wordlist.txt
new file mode 100644
index 00000000..83d83804
--- /dev/null
+++ b/docs-rtd/.custom_wordlist.txt
@@ -0,0 +1,16 @@
+CIDRs
+CPUs
+Hashicorp
+MicroK
+Multipass
+SREs
+TLS
+Terraform
+Unexpose
+declaratively
+juju
+localhost
+macOS
+natively
+terraform
+unexpose
diff --git a/docs-rtd/.gitignore b/docs-rtd/.gitignore
new file mode 100644
index 00000000..468749d8
--- /dev/null
+++ b/docs-rtd/.gitignore
@@ -0,0 +1,17 @@
+
+# Starter pack rules start here
+/*env*/
+.sphinx/venv/
+.sphinx/warnings.txt
+.sphinx/.wordlist.dic
+.sphinx/.doctrees/
+.sphinx/node_modules/
+package*.json
+_build
+.DS_Store
+__pycache__
+.idea/
+.vscode/
+.sphinx/styles/*
+.sphinx/vale.ini
+sp-docs/_build
\ No newline at end of file
diff --git a/docs-rtd/.sphinx/.markdownlint.json b/docs-rtd/.sphinx/.markdownlint.json
new file mode 100644
index 00000000..2fcf6cae
--- /dev/null
+++ b/docs-rtd/.sphinx/.markdownlint.json
@@ -0,0 +1,22 @@
+{
+ "default": false,
+ "MD003": {
+ "style": "atx"
+ },
+ "MD013": false,
+ "MD014": true,
+ "MD018": true,
+ "MD022": true,
+ "MD023": true,
+ "MD026": {
+ "punctuation": ".,;。,;"
+ },
+ "MD031": {
+ "list_items": false
+ },
+ "MD032": true,
+ "MD035": true,
+ "MD042": true,
+ "MD045": true,
+ "MD052": true
+}
diff --git a/docs-rtd/.sphinx/.wordlist.txt b/docs-rtd/.sphinx/.wordlist.txt
new file mode 100644
index 00000000..be5021a1
--- /dev/null
+++ b/docs-rtd/.sphinx/.wordlist.txt
@@ -0,0 +1,64 @@
+ACME
+ACME's
+addons
+AGPLv
+API
+APIs
+balancer
+Charmhub
+CLI
+DCO
+Diátaxis
+Dqlite
+dropdown
+EBS
+EKS
+enablement
+favicon
+Furo
+Git
+GitHub
+Grafana
+IAM
+installable
+JSON
+Juju
+Kubeflow
+Kubernetes
+Launchpad
+linter
+LTS
+LXD
+Makefile
+Makefiles
+Matrix
+Mattermost
+MicroCeph
+MicroCloud
+MicroOVN
+MyST
+namespace
+namespaces
+NodePort
+Numbat
+observability
+OEM
+OLM
+Permalink
+pre
+Quickstart
+ReadMe
+reST
+reStructuredText
+roadmap
+RTD
+subdirectories
+subfolders
+subtree
+TODO
+Ubuntu
+UI
+UUID
+VM
+webhook
+YAML
diff --git a/docs-rtd/.sphinx/_static/css/pdf.css b/docs-rtd/.sphinx/_static/css/pdf.css
new file mode 100644
index 00000000..f9e28dd2
--- /dev/null
+++ b/docs-rtd/.sphinx/_static/css/pdf.css
@@ -0,0 +1,15 @@
+/* Only relevant for specific PDF generation issues */
+
+.rubric>.hclass2 {
+ display: block;
+ font-size: 2em;
+ border-radius: .5rem;
+ font-weight: 300;
+ line-height: 1.25;
+ margin-top: 1.75rem;
+ margin-right: -0.5rem;
+ margin-bottom: 0.5rem;
+ margin-left: -0.5rem;
+ padding-left: .5rem;
+ padding-right: .5rem;
+}
\ No newline at end of file
diff --git a/docs-rtd/.sphinx/_static/favicon.png b/docs-rtd/.sphinx/_static/favicon.png
new file mode 100644
index 00000000..7f175e46
Binary files /dev/null and b/docs-rtd/.sphinx/_static/favicon.png differ
diff --git a/docs-rtd/.sphinx/_static/tag.png b/docs-rtd/.sphinx/_static/tag.png
new file mode 100644
index 00000000..f6f6e5aa
Binary files /dev/null and b/docs-rtd/.sphinx/_static/tag.png differ
diff --git a/docs-rtd/.sphinx/_templates/header.html b/docs-rtd/.sphinx/_templates/header.html
new file mode 100644
index 00000000..f9848fe0
--- /dev/null
+++ b/docs-rtd/.sphinx/_templates/header.html
@@ -0,0 +1,52 @@
+
\ No newline at end of file
diff --git a/docs-rtd/.sphinx/fonts/LICENCE.txt b/docs-rtd/.sphinx/fonts/LICENCE.txt
new file mode 100644
index 00000000..ae78a8f9
--- /dev/null
+++ b/docs-rtd/.sphinx/fonts/LICENCE.txt
@@ -0,0 +1,96 @@
+-------------------------------
+UBUNTU FONT LICENCE Version 1.0
+-------------------------------
+
+PREAMBLE
+This licence allows the licensed fonts to be used, studied, modified and
+redistributed freely. The fonts, including any derivative works, can be
+bundled, embedded, and redistributed provided the terms of this licence
+are met. The fonts and derivatives, however, cannot be released under
+any other licence. The requirement for fonts to remain under this
+licence does not require any document created using the fonts or their
+derivatives to be published under this licence, as long as the primary
+purpose of the document is not to be a vehicle for the distribution of
+the fonts.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this licence and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Original Version" refers to the collection of Font Software components
+as received under this licence.
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to
+a new environment.
+
+"Copyright Holder(s)" refers to all individuals and companies who have a
+copyright ownership of the Font Software.
+
+"Substantially Changed" refers to Modified Versions which can be easily
+identified as dissimilar to the Font Software by users of the Font
+Software comparing the Original Version with the Modified Version.
+
+To "Propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification and with or without charging
+a redistribution fee), making available to the public, and in some
+countries other activities as well.
+
+PERMISSION & CONDITIONS
+This licence does not grant any rights under trademark law and all such
+rights are reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of the Font Software, to propagate the Font Software, subject to
+the below conditions:
+
+1) Each copy of the Font Software must contain the above copyright
+notice and this licence. These can be included either as stand-alone
+text files, human-readable headers or in the appropriate machine-
+readable metadata fields within text or binary files as long as those
+fields can be easily viewed by the user.
+
+2) The font name complies with the following:
+(a) The Original Version must retain its name, unmodified.
+(b) Modified Versions which are Substantially Changed must be renamed to
+avoid use of the name of the Original Version or similar names entirely.
+(c) Modified Versions which are not Substantially Changed must be
+renamed to both (i) retain the name of the Original Version and (ii) add
+additional naming elements to distinguish the Modified Version from the
+Original Version. The name of such Modified Versions must be the name of
+the Original Version, with "derivative X" where X represents the name of
+the new work, appended to that name.
+
+3) The name(s) of the Copyright Holder(s) and any contributor to the
+Font Software shall not be used to promote, endorse or advertise any
+Modified Version, except (i) as required by this licence, (ii) to
+acknowledge the contribution(s) of the Copyright Holder(s) or (iii) with
+their explicit written permission.
+
+4) The Font Software, modified or unmodified, in part or in whole, must
+be distributed entirely under this licence, and must not be distributed
+under any other licence. The requirement for fonts to remain under this
+licence does not affect any document created using the Font Software,
+except any version of the Font Software extracted from a document
+created using the Font Software may only be distributed under this
+licence.
+
+TERMINATION
+This licence becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
+COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER
+DEALINGS IN THE FONT SOFTWARE.
diff --git a/docs-rtd/.sphinx/fonts/Ubuntu-B.ttf b/docs-rtd/.sphinx/fonts/Ubuntu-B.ttf
new file mode 100644
index 00000000..b173da27
Binary files /dev/null and b/docs-rtd/.sphinx/fonts/Ubuntu-B.ttf differ
diff --git a/docs-rtd/.sphinx/fonts/Ubuntu-R.ttf b/docs-rtd/.sphinx/fonts/Ubuntu-R.ttf
new file mode 100644
index 00000000..d748728a
Binary files /dev/null and b/docs-rtd/.sphinx/fonts/Ubuntu-R.ttf differ
diff --git a/docs-rtd/.sphinx/fonts/Ubuntu-RI.ttf b/docs-rtd/.sphinx/fonts/Ubuntu-RI.ttf
new file mode 100644
index 00000000..4f2d2bc7
Binary files /dev/null and b/docs-rtd/.sphinx/fonts/Ubuntu-RI.ttf differ
diff --git a/docs-rtd/.sphinx/fonts/UbuntuMono-B.ttf b/docs-rtd/.sphinx/fonts/UbuntuMono-B.ttf
new file mode 100644
index 00000000..7bd66657
Binary files /dev/null and b/docs-rtd/.sphinx/fonts/UbuntuMono-B.ttf differ
diff --git a/docs-rtd/.sphinx/fonts/UbuntuMono-R.ttf b/docs-rtd/.sphinx/fonts/UbuntuMono-R.ttf
new file mode 100644
index 00000000..fdd309d7
Binary files /dev/null and b/docs-rtd/.sphinx/fonts/UbuntuMono-R.ttf differ
diff --git a/docs-rtd/.sphinx/fonts/UbuntuMono-RI.ttf b/docs-rtd/.sphinx/fonts/UbuntuMono-RI.ttf
new file mode 100644
index 00000000..18f81a29
Binary files /dev/null and b/docs-rtd/.sphinx/fonts/UbuntuMono-RI.ttf differ
diff --git a/docs-rtd/.sphinx/get_vale_conf.py b/docs-rtd/.sphinx/get_vale_conf.py
new file mode 100644
index 00000000..9ee2d0b5
--- /dev/null
+++ b/docs-rtd/.sphinx/get_vale_conf.py
@@ -0,0 +1,53 @@
+#! /usr/bin/env python
+
+import requests
+import os
+
+DIR = os.getcwd()
+
+
+def main():
+ if os.path.exists(f"{DIR}/.sphinx/styles/Canonical"):
+ print("Vale directory exists")
+ else:
+ os.makedirs(f"{DIR}/.sphinx/styles/Canonical")
+
+ url = (
+ "https://api.github.com/repos/canonical/praecepta/"
+ + "contents/styles/Canonical"
+ )
+ r = requests.get(url)
+ for item in r.json():
+ download = requests.get(item["download_url"])
+ file = open(".sphinx/styles/Canonical/" + item["name"], "w")
+ file.write(download.text)
+ file.close()
+
+ if os.path.exists(f"{DIR}/.sphinx/styles/config/vocabularies/Canonical"):
+ print("Vocab directory exists")
+ else:
+ os.makedirs(f"{DIR}/.sphinx/styles/config/vocabularies/Canonical")
+
+ url = (
+ "https://api.github.com/repos/canonical/praecepta/"
+ + "contents/styles/config/vocabularies/Canonical"
+ )
+ r = requests.get(url)
+ for item in r.json():
+ download = requests.get(item["download_url"])
+ file = open(
+ ".sphinx/styles/config/vocabularies/Canonical/" + item["name"],
+ "w"
+ )
+ file.write(download.text)
+ file.close()
+ config = requests.get(
+ "https://raw.githubusercontent.com/canonical/praecepta/main/vale.ini"
+ )
+ file = open(".sphinx/vale.ini", "w")
+ file.write(config.text)
+ file.close()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/docs-rtd/.sphinx/images/Canonical-logo-4x.png b/docs-rtd/.sphinx/images/Canonical-logo-4x.png
new file mode 100644
index 00000000..fd75696e
Binary files /dev/null and b/docs-rtd/.sphinx/images/Canonical-logo-4x.png differ
diff --git a/docs-rtd/.sphinx/images/front-page-light.pdf b/docs-rtd/.sphinx/images/front-page-light.pdf
new file mode 100644
index 00000000..bb68cdf8
Binary files /dev/null and b/docs-rtd/.sphinx/images/front-page-light.pdf differ
diff --git a/docs-rtd/.sphinx/images/normal-page-footer.pdf b/docs-rtd/.sphinx/images/normal-page-footer.pdf
new file mode 100644
index 00000000..dfd73cbc
Binary files /dev/null and b/docs-rtd/.sphinx/images/normal-page-footer.pdf differ
diff --git a/docs-rtd/.sphinx/latex_elements_template.txt b/docs-rtd/.sphinx/latex_elements_template.txt
new file mode 100644
index 00000000..322412c7
--- /dev/null
+++ b/docs-rtd/.sphinx/latex_elements_template.txt
@@ -0,0 +1,119 @@
+{
+ 'papersize': 'a4paper',
+ 'pointsize': '11pt',
+ 'fncychap': '',
+ 'preamble': r'''
+%\usepackage{charter}
+%\usepackage[defaultsans]{lato}
+%\usepackage{inconsolata}
+\setmainfont[UprightFont = *-R, BoldFont = *-B, ItalicFont=*-RI, Extension = .ttf]{Ubuntu}
+\setmonofont[UprightFont = *-R, BoldFont = *-B, ItalicFont=*-RI, Extension = .ttf]{UbuntuMono}
+\usepackage[most]{tcolorbox}
+\tcbuselibrary{breakable}
+\usepackage{lastpage}
+\usepackage{tabto}
+\usepackage{ifthen}
+\usepackage{etoolbox}
+\usepackage{fancyhdr}
+\usepackage{graphicx}
+\usepackage{titlesec}
+\usepackage{fontspec}
+\usepackage{tikz}
+\usepackage{changepage}
+\usepackage{array}
+\usepackage{tabularx}
+\definecolor{yellowgreen}{RGB}{154, 205, 50}
+\definecolor{title}{RGB}{76, 17, 48}
+\definecolor{subtitle}{RGB}{116, 27, 71}
+\definecolor{label}{RGB}{119, 41, 100}
+\definecolor{copyright}{RGB}{174, 167, 159}
+\makeatletter
+\def\tcb@finalize@environment{%
+ \color{.}% hack for xelatex
+ \tcb@layer@dec%
+}
+\makeatother
+\newenvironment{sphinxclassprompt}{\color{yellowgreen}\setmonofont[Color = 9ACD32, UprightFont = *-R, Extension = .ttf]{UbuntuMono}}{}
+\tcbset{enhanced jigsaw, colback=black, fontupper=\color{white}}
+\newtcolorbox{termbox}{use color stack, breakable, colupper=white, halign=flush left}
+\newenvironment{sphinxclassterminal}{\setmonofont[Color = white, UprightFont = *-R, Extension = .ttf]{UbuntuMono}\sphinxsetup{VerbatimColor={black}}\begin{termbox}}{\end{termbox}}
+\newcommand{\dimtorightedge}{%
+ \dimexpr\paperwidth-1in-\hoffset-\oddsidemargin\relax}
+\newcommand{\dimtotop}{%
+ \dimexpr\height-1in-\voffset-\topmargin-\headheight-\headsep\relax}
+\newtoggle{tpage}
+\AtBeginEnvironment{titlepage}{\global\toggletrue{tpage}}
+\fancypagestyle{plain}{
+ \fancyhf{}
+ \fancyfoot[R]{\thepage\ of \pageref*{LastPage}}
+ \renewcommand{\headrulewidth}{0pt}
+ \renewcommand{\footrulewidth}{0pt}
+}
+\fancypagestyle{normal}{
+ \fancyhf{}
+ \fancyfoot[R]{\thepage\ of \pageref*{LastPage}}
+ \renewcommand{\headrulewidth}{0pt}
+ \renewcommand{\footrulewidth}{0pt}
+}
+\fancypagestyle{titlepage}{%
+ \fancyhf{}
+ \fancyfoot[L]{\footnotesize \textcolor{copyright}{© 2024 Canonical Ltd. All rights reserved.}}
+}
+\newcommand\sphinxbackoftitlepage{\thispagestyle{titlepage}}
+\titleformat{\chapter}[block]{\Huge \color{title} \bfseries\filright}{\thechapter .}{1.5ex}{}
+\titlespacing{\chapter}{0pt}{0pt}{0pt}
+\titleformat{\section}[block]{\huge \bfseries\filright}{\thesection .}{1.5ex}{}
+\titlespacing{\section}{0pt}{0pt}{0pt}
+\titleformat{\subsection}[block]{\Large \bfseries\filright}{\thesubsection .}{1.5ex}{}
+\titlespacing{\subsection}{0pt}{0pt}{0pt}
+\setcounter{tocdepth}{1}
+\renewcommand\pagenumbering[1]{}
+''',
+ 'sphinxsetup': 'verbatimwithframe=false, pre_border-radius=0pt, verbatimvisiblespace=\\phantom{}, verbatimcontinued=\\phantom{}',
+ 'extraclassoptions': 'openany,oneside',
+ 'maketitle': r'''
+\begin{titlepage}
+\begin{flushleft}
+ \begin{tikzpicture}[remember picture,overlay]
+ \node[anchor=south east, inner sep=0] at (current page.south east) {
+ \includegraphics[width=\paperwidth, height=\paperheight]{front-page-light}
+ };
+ \end{tikzpicture}
+\end{flushleft}
+
+\vspace*{3cm}
+
+\begin{adjustwidth}{8cm}{0pt}
+\begin{flushleft}
+ \huge \textcolor{black}{\textbf{}{\raggedright{$PROJECT}}}
+\end{flushleft}
+\end{adjustwidth}
+
+\vfill
+
+\begin{adjustwidth}{8cm}{0pt}
+\begin{tabularx}{0.5\textwidth}{ l l }
+ \textcolor{lightgray}{© 2024 Canonical Ltd.} & \hspace{3cm} \\
+ \textcolor{lightgray}{All rights reserved.} & \hspace{3cm} \\
+ & \hspace{3cm} \\
+ & \hspace{3cm} \\
+
+\end{tabularx}
+\end{adjustwidth}
+
+\end{titlepage}
+\RemoveFromHook{shipout/background}
+\AddToHook{shipout/background}{
+ \begin{tikzpicture}[remember picture,overlay]
+ \node[anchor=south west, align=left, inner sep=0] at (current page.south west) {
+ \includegraphics[width=\paperwidth]{normal-page-footer}
+ };
+ \end{tikzpicture}
+ \begin{tikzpicture}[remember picture,overlay]
+ \node[anchor=north east, opacity=0.5, inner sep=35] at (current page.north east) {
+ \includegraphics[width=4cm]{Canonical-logo-4x}
+ };
+ \end{tikzpicture}
+ }
+''',
+}
\ No newline at end of file
diff --git a/docs-rtd/.sphinx/metrics/build_metrics.sh b/docs-rtd/.sphinx/metrics/build_metrics.sh
new file mode 100755
index 00000000..bd1ff1cb
--- /dev/null
+++ b/docs-rtd/.sphinx/metrics/build_metrics.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+# shellcheck disable=all
+
+links=0
+images=0
+
+# count number of links
+links=$(find . -type d -path './.sphinx' -prune -o -name '*.html' -exec cat {} + | grep -o " \n" \
+ "------------------------------------------------------------- \n"
+
+%:
+ $(MAKE) -f Makefile.sp sp-$@
diff --git a/docs-rtd/Makefile.sp b/docs-rtd/Makefile.sp
new file mode 100644
index 00000000..beaf79df
--- /dev/null
+++ b/docs-rtd/Makefile.sp
@@ -0,0 +1,170 @@
+# Minimal makefile for Sphinx documentation
+#
+# `Makefile.sp` is from the Sphinx starter pack and should not be
+# modified.
+# Add your customisation to `Makefile` instead.
+
+# You can set these variables from the command line, and also
+# from the environment for the first two.
+SPHINXDIR = .sphinx
+SPHINXOPTS ?= -c . -d $(SPHINXDIR)/.doctrees -j auto
+SPHINXBUILD ?= $(VENVDIR)/bin/sphinx-build
+SOURCEDIR = .
+BUILDDIR = _build
+VENVDIR = $(SPHINXDIR)/venv
+PA11Y = $(SPHINXDIR)/node_modules/pa11y/bin/pa11y.js --config $(SPHINXDIR)/pa11y.json
+VENV = $(VENVDIR)/bin/activate
+TARGET = *
+ALLFILES = *.rst **/*.rst
+METRICSDIR = $(SOURCEDIR)/.sphinx/metrics
+REQPDFPACKS = latexmk fonts-freefont-otf texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended texlive-font-utils texlive-lang-cjk texlive-xetex plantuml xindy tex-gyre dvipng
+CONFIRM_SUDO ?= N
+
+.PHONY: sp-full-help sp-woke-install sp-spellcheck-install sp-pa11y-install sp-install sp-run sp-html \
+ sp-epub sp-serve sp-clean sp-clean-doc sp-spelling sp-spellcheck sp-linkcheck sp-woke \
+ sp-allmetrics sp-pa11y sp-pdf-prep-force sp-pdf-prep sp-pdf Makefile.sp sp-vale sp-bash
+
+sp-full-help: $(VENVDIR)
+ @. $(VENV); $(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+ @echo "\n\033[1;31mNOTE: This help texts shows unsupported targets!\033[0m"
+ @echo "Run 'make help' to see supported targets."
+
+# If requirements are updated, venv should be rebuilt and timestamped.
+$(VENVDIR):
+ python3 -c "import venv" || \
+ (echo "You must install python3-venv before you can build the documentation."; exit 1)
+ @echo "... setting up virtualenv"
+ python3 -m venv $(VENVDIR)
+ . $(VENV); pip install $(PIPOPTS) --require-virtualenv \
+ --upgrade -r $(SPHINXDIR)/requirements.txt \
+ --log $(VENVDIR)/pip_install.log
+ @test ! -f $(VENVDIR)/pip_list.txt || \
+ mv $(VENVDIR)/pip_list.txt $(VENVDIR)/pip_list.txt.bak
+ @. $(VENV); pip list --local --format=freeze > $(VENVDIR)/pip_list.txt
+ @touch $(VENVDIR)
+
+sp-woke-install:
+ @type woke >/dev/null 2>&1 || \
+ { \
+ echo "Installing system-wide \"woke\" snap..."; \
+ confirm_sudo=$(CONFIRM_SUDO); \
+ if [ "$$confirm_sudo" != "y" ] && [ "$$confirm_sudo" != "Y" ]; then \
+ read -p "This requires sudo privileges. Proceed? [y/N]: " confirm_sudo; \
+ fi; \
+ if [ "$$confirm_sudo" = "y" ] || [ "$$confirm_sudo" = "Y" ]; then \
+ sudo snap install woke; \
+ else \
+ echo "Installation cancelled."; \
+ fi \
+ }
+
+sp-spellcheck-install:
+ @type aspell >/dev/null 2>&1 || \
+ { \
+ echo "Installing system-wide \"aspell\" packages..."; \
+ confirm_sudo=$(CONFIRM_SUDO); \
+ if [ "$$confirm_sudo" != "y" ] && [ "$$confirm_sudo" != "Y" ]; then \
+ read -p "This requires sudo privileges. Proceed? [y/N]: " confirm_sudo; \
+ fi; \
+ if [ "$$confirm_sudo" = "y" ] || [ "$$confirm_sudo" = "Y" ]; then \
+ sudo apt-get install aspell aspell-en; \
+ else \
+ echo "Installation cancelled."; \
+ fi \
+ }
+
+sp-pa11y-install:
+ @type $(PA11Y) >/dev/null 2>&1 || { \
+ echo "Installing \"pa11y\" from npm... \n"; \
+ mkdir -p $(SPHINXDIR)/node_modules/ ; \
+ npm install --prefix $(SPHINXDIR) pa11y; \
+ }
+
+sp-install: $(VENVDIR)
+
+sp-run: sp-install
+ . $(VENV); $(VENVDIR)/bin/sphinx-autobuild -b dirhtml "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS)
+
+# Doesn't depend on $(BUILDDIR) to rebuild properly at every run.
+sp-html: sp-install
+ . $(VENV); $(SPHINXBUILD) -W --keep-going -b dirhtml "$(SOURCEDIR)" "$(BUILDDIR)" -w $(SPHINXDIR)/warnings.txt $(SPHINXOPTS)
+
+sp-epub: sp-install
+ . $(VENV); $(SPHINXBUILD) -b epub "$(SOURCEDIR)" "$(BUILDDIR)" -w $(SPHINXDIR)/warnings.txt $(SPHINXOPTS)
+
+sp-serve: sp-html
+ cd "$(BUILDDIR)"; python3 -m http.server --bind 127.0.0.1 8000
+
+sp-clean: sp-clean-doc
+ @test ! -e "$(VENVDIR)" -o -d "$(VENVDIR)" -a "$(abspath $(VENVDIR))" != "$(VENVDIR)"
+ rm -rf $(VENVDIR)
+ rm -rf $(SPHINXDIR)/node_modules/
+ rm -rf $(SPHINXDIR)/styles
+ rm -rf $(SPHINXDIR)/vale.ini
+
+sp-clean-doc:
+ git clean -fx "$(BUILDDIR)"
+ rm -rf $(SPHINXDIR)/.doctrees
+
+sp-spellcheck: sp-spellcheck-install
+ . $(VENV) ; python3 -m pyspelling -c $(SPHINXDIR)/spellingcheck.yaml -j $(shell nproc)
+
+sp-spelling: sp-html sp-spellcheck
+
+sp-linkcheck: sp-install
+ . $(VENV) ; $(SPHINXBUILD) -b linkcheck "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) || { grep --color -F "[broken]" "$(BUILDDIR)/output.txt"; exit 1; }
+ exit 0
+
+sp-woke: sp-woke-install
+ woke $(ALLFILES) --exit-1-on-failure \
+ -c https://raw.githubusercontent.com/canonical/Inclusive-naming/main/config.yml
+
+sp-pa11y: sp-pa11y-install sp-html
+ find $(BUILDDIR) -name *.html -print0 | xargs -n 1 -0 $(PA11Y)
+
+sp-vale: sp-install
+ @. $(VENV); test -d $(SPHINXDIR)/venv/lib/python*/site-packages/vale || pip install vale
+ @. $(VENV); test -f $(SPHINXDIR)/vale.ini || python3 $(SPHINXDIR)/get_vale_conf.py
+ @. $(VENV); find $(SPHINXDIR)/venv/lib/python*/site-packages/vale/vale_bin -size 195c -exec vale --config "$(SPHINXDIR)/vale.ini" $(TARGET) > /dev/null \;
+ @cat $(SPHINXDIR)/styles/config/vocabularies/Canonical/accept.txt > $(SPHINXDIR)/styles/config/vocabularies/Canonical/accept_backup.txt
+ @cat $(SPHINXDIR)/.wordlist.txt $(SOURCEDIR)/.custom_wordlist.txt >> $(SPHINXDIR)/styles/config/vocabularies/Canonical/accept.txt
+ @echo ""
+ @echo "Running Vale against $(TARGET). To change target set TARGET= with make command"
+ @echo ""
+ @. $(VENV); vale --config "$(SPHINXDIR)/vale.ini" --glob='*.{md,txt,rst}' $(TARGET) || true
+ @cat $(SPHINXDIR)/styles/config/vocabularies/Canonical/accept_backup.txt > $(SPHINXDIR)/styles/config/vocabularies/Canonical/accept.txt && rm $(SPHINXDIR)/styles/config/vocabularies/Canonical/accept_backup.txt
+
+sp-pdf-prep: sp-install
+ @for packageName in $(REQPDFPACKS); do (dpkg-query -W -f='$${Status}' $$packageName 2>/dev/null | \
+ grep -c "ok installed" >/dev/null && echo "Package $$packageName is installed") && continue || \
+ (echo "\nPDF generation requires the installation of the following packages: $(REQPDFPACKS)" && \
+ echo "" && echo "Run 'sudo make pdf-prep-force' to install these packages" && echo "" && echo \
+ "Please be aware these packages will be installed to your system") && exit 1 ; done
+
+sp-pdf-prep-force:
+ apt-get update
+ apt-get upgrade -y
+ apt-get install --no-install-recommends -y $(REQPDFPACKS) \
+
+sp-pdf: sp-pdf-prep
+ @. $(VENV); sphinx-build -M latexpdf "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS)
+ @rm ./$(BUILDDIR)/latex/front-page-light.pdf || true
+ @rm ./$(BUILDDIR)/latex/normal-page-footer.pdf || true
+ @find ./$(BUILDDIR)/latex -name "*.pdf" -exec mv -t ./$(BUILDDIR) {} +
+ @rm -r $(BUILDDIR)/latex
+ @echo "\nOutput can be found in ./$(BUILDDIR)\n"
+
+sp-allmetrics: sp-html
+ @echo "Recording documentation metrics..."
+ @echo "Checking for existence of vale..."
+ . $(VENV)
+ @. $(VENV); test -d $(SPHINXDIR)/venv/lib/python*/site-packages/vale || pip install vale
+ @. $(VENV); test -f $(SPHINXDIR)/vale.ini || python3 $(SPHINXDIR)/get_vale_conf.py
+ @. $(VENV); find $(SPHINXDIR)/venv/lib/python*/site-packages/vale/vale_bin -size 195c -exec vale --config "$(SPHINXDIR)/vale.ini" $(TARGET) > /dev/null \;
+ @eval '$(METRICSDIR)/source_metrics.sh $(PWD)'
+ @eval '$(METRICSDIR)/build_metrics.sh $(PWD) $(METRICSDIR)'
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile.sp
+ . $(VENV); $(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/docs-rtd/conf.py b/docs-rtd/conf.py
new file mode 100644
index 00000000..9942dba9
--- /dev/null
+++ b/docs-rtd/conf.py
@@ -0,0 +1,324 @@
+import datetime
+import ast
+
+# Configuration for the Sphinx documentation builder.
+# All configuration specific to your project should be done in this file.
+#
+# If you're new to Sphinx and don't want any advanced or custom features,
+# just go through the items marked 'TODO'.
+#
+# A complete list of built-in Sphinx configuration values:
+# https://www.sphinx-doc.org/en/master/usage/configuration.html
+#
+# Our starter pack uses the custom Canonical Sphinx extension
+# to keep all documentation based on it consistent and on brand:
+# https://github.com/canonical/canonical-sphinx
+
+
+#######################
+# Project information #
+#######################
+
+# Project name
+#
+# TODO: Update with the official name of your project or product
+
+project = "Terraform Provider for Juju"
+author = "Canonical Ltd."
+
+
+# Sidebar documentation title; best kept reasonably short
+#
+# TODO: To include a version number, add it here (hardcoded or automated).
+#
+# TODO: To disable the title, set to an empty string.
+
+html_title = project + " documentation"
+
+
+# Copyright string; shown at the bottom of the page
+#
+# Now, the starter pack uses CC-BY-SA as the license
+# and the current year as the copyright year.
+#
+# TODO: If your docs need another license, specify it instead of 'CC-BY-SA'.
+#
+# TODO: If your documentation is a part of the code repository of your project,
+# it inherits the code license instead; specify it instead of 'CC-BY-SA'.
+#
+# NOTE: For static works, it is common to provide the first publication year.
+# Another option is to provide both the first year of publication
+# and the current year, especially for docs that frequently change,
+# e.g. 2022–2023 (note the en-dash).
+#
+# A way to check a repo's creation date is to get a classic GitHub token
+# with 'repo' permissions; see https://github.com/settings/tokens
+# Next, use 'curl' and 'jq' to extract the date from the API's output:
+#
+# curl -H 'Authorization: token ' \
+# -H 'Accept: application/vnd.github.v3.raw' \
+# https://api.github.com/repos/canonical/ | jq '.created_at'
+
+copyright = "%s CC-BY-SA, %s" % (datetime.date.today().year, author)
+
+
+# Documentation website URL
+#
+# TODO: Update with the official URL of your docs or leave empty if unsure.
+#
+# NOTE: The Open Graph Protocol (OGP) enhances page display in a social graph
+# and is used by social media platforms; see https://ogp.me/
+
+ogp_site_url = "https://canonical-terraform-provider-juju.readthedocs-hosted.com/"
+
+
+# Preview name of the documentation website
+#
+# TODO: To use a different name for the project in previews, update as needed.
+
+ogp_site_name = project
+
+
+# Preview image URL
+#
+# TODO: To customise the preview image, update as needed.
+
+ogp_image = "https://assets.ubuntu.com/v1/253da317-image-document-ubuntudocs.svg"
+
+
+# Product favicon; shown in bookmarks, browser tabs, etc.
+
+# TODO: To customise the favicon, uncomment and update as needed.
+
+# html_favicon = '.sphinx/_static/favicon.png'
+
+
+# Dictionary of values to pass into the Sphinx context for all pages:
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-html_context
+
+html_context = {
+ # Product page URL; can be different from product docs URL
+ #
+ # TODO: Change to your product website URL,
+ # dropping the 'https://' prefix, e.g. 'ubuntu.com/lxd'.
+ #
+ # TODO: If there's no such website,
+ # remove the {{ product_page }} link from the page header template
+ # (usually .sphinx/_templates/header.html; also, see README.rst).
+ "product_page": "juju.is",
+ # Product tag image; the orange part of your logo, shown in the page header
+ #
+ # TODO: To add a tag image, uncomment and update as needed.
+ # 'product_tag': '_static/tag.png',
+ # Your Discourse instance URL
+ #
+ # TODO: Change to your Discourse instance URL or leave empty.
+ #
+ # NOTE: If set, adding ':discourse: 123' to an .rst file
+ # will add a link to Discourse topic 123 at the bottom of the page.
+ "discourse": "https://discourse.charmhub.io",
+ # Your Mattermost channel URL
+ #
+ # TODO: Change to your Mattermost channel URL or leave empty.
+ # "mattermost":
+ # "https://chat.canonical.com/canonical/channels/documentation",
+ # Your Matrix channel URL
+ #
+ # TODO: Change to your Matrix channel URL or leave empty.
+ "matrix": "https://matrix.to/#/#terraform-provider-juju:ubuntu.com",
+ # Your documentation GitHub repository URL
+ #
+ # TODO: Change to your documentation GitHub repository URL or leave empty.
+ #
+ # NOTE: If set, links for viewing the documentation source files
+ # and creating GitHub issues are added at the bottom of each page.
+ "github_url": "https://github.com/juju/terraform-provider-juju",
+ # Docs branch in the repo; used in links for viewing the source files
+ #
+ # TODO: To customise the branch, uncomment and update as needed.
+ # 'github_version': 'main',
+ # Docs location in the repo; used in links for viewing the source files
+ #
+ # TODO: To customise the directory, uncomment and update as needed.
+ "github_folder": "/docs-rtd/",
+
+ # TODO: To enable or disable the Previous / Next buttons at the bottom of pages
+ # Valid options: none, prev, next, both
+ # "sequential_nav": "both",
+}
+
+# Project slug; see https://meta.discourse.org/t/what-is-category-slug/87897
+#
+# TODO: If your documentation is hosted on https://docs.ubuntu.com/,
+# uncomment and update as needed.
+
+# slug = ''
+
+
+# Template and asset locations
+
+html_static_path = [".sphinx/_static"]
+templates_path = [".sphinx/_templates"]
+
+
+#############
+# Redirects #
+#############
+
+# To set up redirects: https://documatt.gitlab.io/sphinx-reredirects/usage.html
+# For example: 'explanation/old-name.html': '../how-to/prettify.html',
+
+# To set up redirects in the Read the Docs project dashboard:
+# https://docs.readthedocs.io/en/stable/guides/redirects.html
+
+# NOTE: If undefined, set to None, or empty,
+# the sphinx_reredirects extension will be disabled.
+
+redirects = {}
+
+
+###########################
+# Link checker exceptions #
+###########################
+
+# A regex list of URLs that are ignored by 'make linkcheck'
+#
+# TODO: Remove or adjust the ACME entry after you update the contributing guide
+
+linkcheck_ignore = [
+ "http://127.0.0.1:8000",
+ "https://github.com/canonical/ACME/*"
+]
+
+
+# A regex list of URLs where anchors are ignored by 'make linkcheck'
+
+linkcheck_anchors_ignore_for_url = [
+ r"https://github\.com/.*",
+ r"https://juju\.is/.*",
+ r"https://matrix\.to/.*",
+ r"https://registry\.terraform\.io/.*",
+]
+
+
+########################
+# Configuration extras #
+########################
+
+# Custom MyST syntax extensions; see
+# https://myst-parser.readthedocs.io/en/latest/syntax/optional.html
+#
+# NOTE: By default, the following MyST extensions are enabled:
+# substitution, deflist, linkify
+
+myst_enable_extensions = {
+ 'colon_fence',
+}
+
+# Custom Sphinx extensions; see
+# https://www.sphinx-doc.org/en/master/usage/extensions/index.html
+
+# NOTE: The canonical_sphinx extension is required for the starter pack.
+# It automatically enables the following extensions:
+# - custom-rst-roles
+# - myst_parser
+# - notfound.extension
+# - related-links
+# - sphinx_copybutton
+# - sphinx_design
+# - sphinx_reredirects
+# - sphinx_tabs.tabs
+# - sphinxcontrib.jquery
+# - sphinxext.opengraph
+# - terminal-output
+# - youtube-links
+
+extensions = [
+ "canonical_sphinx",
+ "sphinxcontrib.cairosvgconverter",
+]
+
+
+# Excludes files or directories from processing
+
+exclude_patterns = [
+ "doc-cheat-sheet*",
+]
+
+# Adds custom CSS files, located under 'html_static_path'
+
+html_css_files = [
+ "css/pdf.css",
+]
+
+
+# Adds custom JavaScript files, located under 'html_static_path'
+
+# html_js_files = []
+
+
+# Specifies a reST snippet to be appended to each .rst file
+
+rst_epilog = """
+.. include:: /reuse/links.txt
+"""
+
+# Feedback button at the top; enabled by default
+#
+# TODO: To disable the button, uncomment this.
+
+# disable_feedback_button = True
+
+
+# Your manpage URL
+#
+# TODO: To enable manpage links, uncomment and update as needed.
+#
+# NOTE: If set, adding ':manpage:' to an .rst file
+# adds a link to the corresponding man section at the bottom of the page.
+
+# manpages_url = f'https://manpages.ubuntu.com/manpages/{codename}/en/' + \
+# f'man{section}/{page}.{section}.html'
+
+
+# Specifies a reST snippet to be prepended to each .rst file
+# This defines a :center: role that centers table cell content.
+# This defines a :h2: role that styles content for use with PDF generation.
+
+rst_prolog = """
+.. role:: center
+ :class: align-center
+.. role:: h2
+ :class: hclass2
+"""
+
+# Workaround for https://github.com/canonical/canonical-sphinx/issues/34
+
+if "discourse_prefix" not in html_context and "discourse" in html_context:
+ html_context["discourse_prefix"] = html_context["discourse"] + "/t/"
+
+#####################
+# PDF configuration #
+#####################
+
+latex_additional_files = [
+ "./.sphinx/fonts/Ubuntu-B.ttf",
+ "./.sphinx/fonts/Ubuntu-R.ttf",
+ "./.sphinx/fonts/Ubuntu-RI.ttf",
+ "./.sphinx/fonts/UbuntuMono-R.ttf",
+ "./.sphinx/fonts/UbuntuMono-RI.ttf",
+ "./.sphinx/fonts/UbuntuMono-B.ttf",
+ "./.sphinx/images/Canonical-logo-4x.png",
+ "./.sphinx/images/front-page-light.pdf",
+ "./.sphinx/images/normal-page-footer.pdf",
+]
+
+latex_engine = "xelatex"
+latex_show_pagerefs = True
+latex_show_urls = "footnote"
+
+with open(".sphinx/latex_elements_template.txt", "rt") as file:
+ latex_config = file.read()
+
+latex_elements = ast.literal_eval(latex_config.replace("$PROJECT", project))
+
diff --git a/docs-rtd/contributing.md b/docs-rtd/contributing.md
new file mode 100644
index 00000000..cb664bb2
--- /dev/null
+++ b/docs-rtd/contributing.md
@@ -0,0 +1,183 @@
+---
+orphan: true
+---
+
+
+
+
+# How to contribute
+
+We believe that everyone has something valuable to contribute, whether you're a coder, a writer, or a tester. Here's how and why you can get involved:
+
+- **Why join us?** Work with like-minded people, develop your skills, connect with diverse professionals, and make a difference.
+- **What do you get?** Personal growth, recognition for your contributions, early access to new features, and the joy of seeing your work appreciated.
+- **Start early, start easy**: Dive into code contributions, improve documentation, or be among the first testers. Your presence matters, regardless of experience or the size of your contribution.
+
+The guidelines below will help keep your contributions effective and meaningful.
+
+## Code of conduct
+
+When contributing, you must abide by the [Ubuntu Code of Conduct](https://ubuntu.com/community/ethos/code-of-conduct).
+
+## Licence and copyright
+
+
+
+By default, all contributions to ACME are made under the AGPLv3 licence. See the [licence](https://github.com/canonical/ACME/blob/main/COPYING) in the ACME GitHub repository for details.
+
+All contributors must sign the [Canonical contributor licence agreement](https://ubuntu.com/legal/contributors), which grants Canonical permission to use the contributions. The author of a change remains the copyright owner of their code (no copyright assignment occurs).
+
+## Releases and versions
+
+
+
+ACME uses [semantic versioning](https://semver.org/); major releases occur once or twice a year.
+
+The release notes can be found TODO: [here](https://example.com).
+
+## Environment setup
+
+
+
+To work on the project, you need the following prerequisites:
+
+- [TODO: Prerequisite 1](http://example.com)
+- [TODO: Prerequisite 2](http://example.com)
+
+To install and configure these tools:
+
+```bash
+TODO: prerequisite command 1
+TODO: prerequisite command 2
+```
+
+## Submissions
+
+
+
+If you want to address an issue or a bug in ACME, notify in advance the people involved to avoid confusion; also, reference the issue or bug number when you submit the changes.
+
+- Fork [our GitHub repository](https://github.com/canonical/ACME) and add the changes to your fork, properly structuring your commits, providing detailed commit messages, and signing your commits.
+
+- Make sure the updated project builds and runs without warnings or errors; this includes linting, documentation, code, and tests.
+
+- Submit the changes as a [pull request (PR)](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork).
+
+Your changes will be reviewed in due time; if approved, they will eventually be merged.
+
+### Describing pull requests
+
+
+
+To be properly considered, reviewed, and merged, your pull request must provide the following details:
+
+- **Title**: Summarise the change in a short, descriptive title.
+- **Description**: Explain the problem that your pull request solves. Mention any new features, bug fixes, or refactoring.
+- **Relevant issues**: Reference any [related issues, pull requests, and repositories](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/autolinked-references-and-urls).
+- **Testing**: Explain whether new or updated tests are included.
+- **Reversibility**: If you propose decisions that may be costly to reverse, list the reasons and suggest steps to reverse the changes if necessary.
+
+### Commit structure and messages
+
+
+
+Use separate commits for each logical change, and for changes to different components. Prefix your commit messages with the names of components they affect, using the code tree structure. For example, start a commit that updates the ACME service with `ACME/service:`.
+
+Use [conventional commits](https://www.conventionalcommits.org/) to ensure consistency across the project:
+
+```none
+Ensure correct permissions and ownership for the content mounts
+
+* Work around an ACME issue regarding empty dirs: https://github.com/canonical/ACME/issues/12345
+
+* Ensure the source directory is owned by the user running a container.
+
+Links:
+- ...
+- ...
+```
+
+Such structure makes it easier to review contributions and simplifies porting fixes to other branches.
+
+### Signing commits
+
+
+
+To improve contribution tracking, we use the developer certificate of origin ([DCO 1.1](https://developercertificate.org/)) and require a "sign-off" for any changes going into each branch.
+
+The sign-off is a simple line at the end of the commit message certifying that you wrote it or have the right to commit it as an open-source contribution.
+
+To sign off on a commit, use the `--signoff` option in `git commit`.
+
+## Code
+
+### Formatting and linting
+
+
+
+ACME relies on these formatting and linting tools:
+
+- [TODO: Tool 1](http://example.com)
+- [TODO: Tool 2](http://example.com)
+
+To configure and run them:
+
+```bash
+TODO: lint command 1
+TODO: lint command 2
+```
+
+### Structure
+
+- **Check linked code elements**: Ensure coupled code elements, files, and directories are adjacent. For instance, store test data close to the corresponding test code.
+- **Group variable declaration and initialisation**: Declare and initialise variables together to improve code organisation and readability.
+- **Split large expressions**: Break down large expressions into smaller self-explanatory parts. Use multiple variables where appropriate to make the code more understandable and choose names that reflect their purpose.
+- **Use blank lines for logical separation**: Insert a blank line between two logically separate sections of code to improve its structure and readability.
+- **Avoid nested conditions**: Avoid nesting conditions to improve readability and maintainability.
+- **Remove dead code and redundant comments**: Drop unused or obsolete code and comments to promote a cleaner code base and reduce confusion.
+- **Normalise symmetries**: Treat identical operations consistently, using a uniform approach to improve consistency and readability.
+
+### Best practices
+
+
+
+## Tests
+
+
+
+All code contributions must include tests.
+
+To run the tests locally before submitting your changes:
+
+```bash
+TODO: test command 1
+TODO: test command 2
+```
+
+## Documentation
+
+ACME's documentation is stored in the `DOCDIR` directory of the repository. It is based on the [Canonical starter pack](https://canonical-starter-pack.readthedocs-hosted.com/latest/) and hosted on [Read the Docs](https://about.readthedocs.com/).
+
+For general guidance, refer to the [starter pack guide](https://canonical-starter-pack.readthedocs-hosted.com/latest/).
+
+For syntax help and guidelines, refer to the [Canonical style guides](https://canonical-documentation-with-sphinx-and-readthedocscom.readthedocs-hosted.com/#style-guides).
+
+In structuring, the documentation employs the [Diátaxis](https://diataxis.fr/) approach.
+
+To run the documentation locally before submitting your changes:
+
+```bash
+make run
+```
+
+### Automatic checks
+
+GitHub runs automatic checks on the documentation to verify spelling, validate links, and suggest inclusive language.
+
+You can (and should) run the same checks locally:
+
+```bash
+make spelling
+make linkcheck
+make woke
+```
diff --git a/docs-rtd/doc-cheat-sheet.md b/docs-rtd/doc-cheat-sheet.md
new file mode 100644
index 00000000..6257c9db
--- /dev/null
+++ b/docs-rtd/doc-cheat-sheet.md
@@ -0,0 +1,261 @@
+---
+orphan: true
+myst:
+ substitutions:
+ reuse_key: "This is **included** text."
+ advanced_reuse_key: "This is a substitution that includes a code block:
+ ```
+ code block
+ ```"
+---
+
+
+
+(cheat-sheet-myst)=
+# Markdown/MyST cheat sheet
+
+
+
+This file contains the syntax for commonly used Markdown and MyST markup.
+Open it in your text editor to quickly copy and paste the markup you need.
+
+See the [MyST style guide](https://canonical-documentation-with-sphinx-and-readthedocscom.readthedocs-hosted.com/style-guide-myst/) for detailed information and conventions.
+
+Also see the [MyST documentation](https://myst-parser.readthedocs.io/en/latest/index.html) for detailed information on MyST, and the [Canonical Documentation Style Guide](https://docs.ubuntu.com/styleguide/en) for general style conventions.
+
+## H2 heading
+
+### H3 heading
+
+#### H4 heading
+
+##### H5 heading
+
+## Inline formatting
+
+- {guilabel}`UI element`
+- `code`
+- {command}`command`
+- {kbd}`Key`
+- *Italic*
+- **Bold**
+
+## Code blocks
+
+Start a code block:
+
+ code:
+ - example: true
+
+```
+# Demonstrate a code block
+code:
+ - example: true
+```
+
+```yaml
+# Demonstrate a code block
+code:
+ - example: true
+```
+
+(a_section_target_myst)=
+## Links
+
+- [Canonical website](https://canonical.com/)
+- {ref}`a_section_target_myst`
+- {ref}`Link text `
+- {doc}`index`
+- {doc}`Link text `
+
+## Navigation
+
+Use the following syntax::
+
+ ```{toctree}
+ :hidden:
+
+ sub-page1
+ sub-page2
+ ```
+
+## Lists
+
+1. Step 1
+ - Item 1
+ * Sub-item
+ - Item 2
+ 1. Sub-step 1
+ 1. Sub-step 2
+1. Step 2
+ 1. Sub-step 1
+ - Item
+ 1. Sub-step 2
+
+Term 1
+: Definition
+
+Term 2
+: Definition
+
+## Tables
+
+## Markdown tables
+
+| Header 1 | Header 2 |
+|------------------------------------|----------|
+| Cell 1
Second paragraph | Cell 2 |
+| Cell 3 | Cell 4 |
+
+Centred:
+
+| Header 1 | Header 2 |
+|:----------------------------------:|:--------:|
+| Cell 1
Second paragraph | Cell 2 |
+| Cell 3 | Cell 4 |
+
+## List tables
+
+```{list-table}
+ :header-rows: 1
+
+* - Header 1
+ - Header 2
+* - Cell 1
+
+ Second paragraph
+ - Cell 2
+* - Cell 3
+ - Cell 4
+```
+
+Centred:
+
+```{list-table}
+ :header-rows: 1
+ :align: center
+
+* - Header 1
+ - Header 2
+* - Cell 1
+
+ Second paragraph
+ - Cell 2
+* - Cell 3
+ - Cell 4
+```
+
+## Notes
+
+```{note}
+A note.
+```
+
+```{tip}
+A tip.
+```
+
+```{important}
+Important information
+```
+
+```{caution}
+This might damage your hardware!
+```
+
+## Images
+
+![Alt text](https://assets.ubuntu.com/v1/b3b72cb2-canonical-logo-166.png)
+
+```{figure} https://assets.ubuntu.com/v1/b3b72cb2-canonical-logo-166.png
+ :width: 100px
+ :alt: Alt text
+
+ Figure caption
+```
+
+## Reuse
+
+### Keys
+
+Keys can be defined at the top of a file, or in a `myst_substitutions` option in `conf.py`.
+
+{{reuse_key}}
+
+{{advanced_reuse_key}}
+
+### File inclusion
+
+```{include} index.md
+ :start-after: include_start
+ :end-before: include_end
+```
+
+## Tabs
+
+````{tabs}
+```{group-tab} Tab 1
+
+Content Tab 1
+```
+
+```{group-tab} Tab 2
+Content Tab 2
+```
+````
+
+## Glossary
+
+```{glossary}
+
+some term
+ Definition of the example term.
+```
+
+{term}`some term`
+
+## More useful markup
+
+- ```{versionadded} X.Y
+- {abbr}`API (Application Programming Interface)`
+
+----
+
+## Custom extensions
+
+Related links at the top of the page (surrounded by `---`):
+
+ relatedlinks: https://github.com/canonical/lxd-sphinx-extensions, [RTFM](https://www.google.com)
+ discourse: 12345
+
+Terms that should not be checked by the spelling checker: {spellexception}`PurposelyWrong`
+
+A single-line terminal view that separates input from output:
+
+```{terminal}
+ :input: command
+ :user: root
+ :host: vampyr
+ :dir: /home/user/directory/
+
+the output
+```
+
+A multi-line version of the same:
+
+```{terminal}
+ :user: root
+ :host: vampyr
+ :dir: /home/user/directory/
+
+:input: command 1
+output 1
+:input: command 2
+output 2
+```
+
+A link to a YouTube video:
+
+```{youtube} https://www.youtube.com/watch?v=iMLiK1fX4I0
+ :title: Demo
+```
diff --git a/docs-rtd/howto/index.md b/docs-rtd/howto/index.md
new file mode 100644
index 00000000..2f684873
--- /dev/null
+++ b/docs-rtd/howto/index.md
@@ -0,0 +1,26 @@
+(howtos)=
+# How-to guides
+
+
+
+```{toctree}
+:maxdepth: 2
+
+Install and manage terraform-provider-juju
+Manage credentials
+Manage models
+Manage charms
+Manage charm resources
+Manage applications
+Manage relations
+Manage offers
+Manage units
+Manage machines
+Manage SSH keys
+Manage users
+Manage secrets
+```
+
+
diff --git a/docs-rtd/howto/install-and-manage-terraform-provider-juju.md b/docs-rtd/howto/install-and-manage-terraform-provider-juju.md
new file mode 100644
index 00000000..0600db5d
--- /dev/null
+++ b/docs-rtd/howto/install-and-manage-terraform-provider-juju.md
@@ -0,0 +1,111 @@
+(install-and-manage-terraform-provider-juju)=
+# How to install and manage `terraform-provider-juju`
+
+## Install `terraform-provider-juju`
+
+To install `terraform-provider-juju` on Linux, macOS, or Windows, you need to install the `terraform` CLI.
+
+> See more: [Hashicorp | Install Terraform](https://developer.hashicorp.com/terraform/install)
+
+For example, on a Linux that supports snaps:
+
+```text
+sudo snap install terraform
+```
+
+(use-terraform-provider-juju)=
+## Use `terraform-provider-juju`
+
+
+Once you've installed the `terraform` CLI, to start using it:
+
+1. **Require the `juju` provider.** In your Terraform plan, under `required_providers`, specify the `juju` provider:
+
+ ```terraform
+ terraform {
+ required_providers {
+ juju = {
+ version = "~> 0.10.0"
+ source = "juju/juju"
+ }
+ }
+ }
+ ```
+
+2. **Configure the provider to use a pre-existing controller.** There are 3 ways you can do this: using static credentials, using environment variables, or using the `juju` client.
+
+ ```{note}
+ For all methods: To view your controller's details, run `juju show-controller --show-password`.
+
+ ```
+
+ ::::{dropdown} Configure the provider using static credentials
+
+ In your Terraform plan, in your provider specification, use the various keywords to provide your controller information statically:
+
+ ```terraform
+ provider "juju" {
+ controller_addresses = "10.225.205.241:17070,10.225.205.242:17070"
+ username = "jujuuser"
+ password = "password1"
+ ca_certificate = file("~/ca-cert.pem")
+ }
+ ```
+
+ > See more: [Terraform | `juju` provider](https://registry.terraform.io/providers/juju/juju/latest/docs)
+
+ ::::
+
+ ::::{dropdown} Configure the provider using environment variables
+
+ In your Terraform plan, leave the `provider` specification empty:
+
+ ```terraform
+ provider "juju" {}
+ ```
+
+ Then, in a terminal, export the controller environment variables with your controller's values. For example:
+
+ ```bash
+ export JUJU_CONTROLLER_ADDRESSES="10.225.205.241:17070,10.225.205.242:17070"
+ export JUJU_USERNAME="jujuuser"
+ export JUJU_PASSWORD="password1"
+ export JUJU_CA_CERT=file("~/ca-cert.pem")
+ ```
+
+ ::::
+
+
+ ::::{dropdown} Configure the provider using the juju CLI
+
+ In your Terraform plan, leave the `provider` specification empty:
+
+ ```terraform
+ provider "juju" {}
+ ```
+
+ Then, in a terminal, use the `juju` client to switch to the desired controller: `juju switch `. Your Terraform plan will be interpreted relative to that controller.
+
+ ::::
+
+3. Build your deployment.
+
+ > See more: [How-to guides](../howto/index)
+
+4. Once you're done, in a terminal, run:
+
+ a. (just the first time) `terraform init` to initialise your project;
+
+ b. `terraform plan` to stage the changes; and
+
+ c. `terraform apply` to apply the changes to your Juju deployment.
+
+
+
+## Upgrade `terraform-provider-juju`
+
+To upgrade `terraform-provider-juju`, in your Terraform plan update the version constraint, then run `terraform init` with the `--upgrade` flag.
+
+> See more: Terraform [Version constraints](https://developer.hashicorp.com/terraform/language/providers/requirements#version-constraints), [`terraform init --upgrade`](https://developer.hashicorp.com/terraform/cli/commands/init#upgrade-1)
+
+> **Contributors:** @cderici, @hmlanigan, @simonrichardson, @timclicks, @tmihoc
diff --git a/docs-rtd/howto/manage-applications.md b/docs-rtd/howto/manage-applications.md
new file mode 100644
index 00000000..c7d5eaee
--- /dev/null
+++ b/docs-rtd/howto/manage-applications.md
@@ -0,0 +1,215 @@
+(manage-applications)=
+# How to manage applications
+
+> See also: [`juju` | Application](https://juju.is/docs/juju/application)
+
+## Deploy an application
+
+To deploy an application, find and deploy a charm that delivers it.
+
+> See more: {ref}`deploy-a-charm`
+
+
+## Set the machine base for an application
+> Only for machine clouds.
+
+TBA
+
+
+## Trust an application with a credential
+
+
+Some applications may require access to the backing cloud in order to fulfil their purpose (e.g., storage-related tasks). In such cases, the remote credential associated with the current model would need to be shared with the application. When the Juju administrator allows this to occur the application is said to be *trusted*.
+
+To trust an application with a credential, in the `juju_application` resource definition, add a `trust` attribute and set it to `true`:
+
+```terraform
+resource "juju_application" "this" {
+ model = juju_model.development.name
+
+ charm {
+ name = "hello-kubecon"
+ }
+
+ trust = true
+}
+```
+
+> See more: [`juju_application` (resource)](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/application#schema)
+
+
+
+## Configure an application
+> See also: [`juju` | Application configuration](https://juju.is/docs/juju/configuration#heading--application-configuration)
+
+To configure an application, in its resource definition add a configuration map with the `key=value` pairs you want (from the list of configurations available for the charm).
+
+```terraform
+resource "juju_application" "this" {
+ model = juju_model.development.name
+
+ charm {
+ name = "hello-kubecon"
+ }
+
+ config = {
+ redirect-map = "https://demo"
+ }
+}
+```
+> See more: [`juju_application` (resource)](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/application#schema)
+
+
+(scale-an-application)=
+## Scale an application
+
+> See also: [`juju`| Scaling](https://juju.is/docs/juju/scaling)
+
+### Scale an application vertically
+
+To scale an application vertically, set constraints for the resources that the application's units will be deployed on.
+
+> See more: {ref}`manage-constraints-for-an-application`
+
+(scale-an-application-horizontally)=
+### Scale an application horizontally
+
+To scale an application horizontally, control the number of units.
+
+> See more: {ref}`control-the-number-of-units`
+
+
+## Make an application highly available
+> See also: [`juju` | High availability (HA)](https://juju.is/docs/juju/high-availability)
+
+1. Find out if the charm delivering the application supports high availability natively or not. If the latter, find out what you need to do. This could mean integrating with a load balancing reverse proxy, configuring storage etc.
+
+> See more: [Charmhub > ``](https://charmhub.io/)
+
+2. Scale up horizontally as usual.
+
+> See more: {ref}`scale-an-application-horizontally`
+
+
+## Integrate an application with another application
+
+> See more: {ref}`manage-relations`
+
+
+## Manage an application’s public availability over the network
+
+**Expose.** To expose an application over a network, in its resource definition use an expose attribute:
+
+```terraform
+resource "juju_application" "this" {
+ model = juju_model.development.name
+
+ charm {
+ name = "hello-kubecon"
+ }
+
+ expose = {}
+}
+```
+
+This will expose all of the application's endpoints. To restrict exposure to just specific endpoints, spaces, or CIDRs, specify nested attributes.
+
+
+
+
+> See more: [`juju_application` > `expose` > nested schema](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/application#nested-schema-for-expose)
+
+
+
+**Unexpose.** To unexpose an application, remove the `expose` attribute from its resource definition.
+
+
+(manage-constraints-for-an-application)=
+## Manage constraints for an application
+
+> See also: [`juju` | Constraint](https://juju.is/docs/juju/constraint)
+
+
+To set constraints for an application, in its resource definition specify a `constraints` attribute followed by a quotes-enclosed, space-separated list of key=value pairs. For example:
+
+```terraform
+resource "juju_application" "this" {
+ model = juju_model.development.name
+
+ charm {
+ name = "hello-kubecon"
+ }
+
+ constraints = "mem=6G cores=2"
+
+}
+```
+
+> See more: [`juju_application` (resource)](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/application#schema)
+
+
+
+## Change space bindings for an application
+
+> See also: [`juju` | Binding](https://juju.is/docs/juju/binding)
+
+
+To set space bindings for an application, in its resource definition specify an `endpoint_bindings` with a `space` key, to set a default for the entire application, and/or a `space` and an `endpoint` key, to set the space binding for a particular application endpoint. For example, below all the application's endpoints are bound to the `public` space except for the `juju-info` endpoint, which will be bound to the `private` space:
+
+```terraform
+resource "juju_application" "application_three" {
+ model = resource.juju_model.testmodel.name
+ charm {
+ name = "juju-qa-test"
+ }
+ units = 0
+ endpoint_bindings = [
+ {
+ "space" = "public"
+ }
+ {
+ "space" = "private"
+ "endpoint" = "juju-info"
+ }
+ ]
+}
+```
+
+> See more: [`juju_application` > `endpoint_bindings`](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/application#endpoint_bindings)
+
+
+
+## Upgrade an application
+
+To upgrade an application, update its charm.
+
+> See more: {ref}`update-a-charm`
+
+(remove-an-application)=
+## Remove an application
+
+> See also: [`juju` | Removing things](https://juju.is/docs/juju/removing-things)
+
+
+To remove an application, remove its resource definition from your Terraform plan.
+
+> See more: [`juju_application` (resource)](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/application#schema)
+
+
+> Contributors: @achilleasa , @cderici, @james-garner, @hmlanigan , @nvinuesa , @pedroleaoc , @pmatulis , @stephanpampel , @timClicks , @tmihoc
diff --git a/docs-rtd/howto/manage-charm-resources.md b/docs-rtd/howto/manage-charm-resources.md
new file mode 100644
index 00000000..95b329c5
--- /dev/null
+++ b/docs-rtd/howto/manage-charm-resources.md
@@ -0,0 +1,47 @@
+(manage-charm-resources)=
+# How to manage charm resources
+
+> See also: [`juju` | Resource (charm)](https://juju.is/docs/juju/charm-resource)
+
+When you deploy / update an application from a charm, that automatically deploys / updates any charm resources, using the defaults specified by the charm author. However, you can also specify resources manually (e.g., to try a resource released only to `edge` or to specify a non-Charmhub resource). This document shows you how.
+
+## Specify the resources to be deployed with a charm
+
+
+To specify the resource(s) to be deployed with your charm, in your Terraform plan, in the definition of the resource for the application specify a `resources` block with key-value pairs listing resource names and their revision number. For example:
+
+```terraform
+resource "juju_application" "application_one" {
+ name = "my-application"
+ model = juju_model.testmodel.name
+
+ charm {
+ name = "juju-qa-test"
+ channel = "2.0/edge"
+ }
+ resources = {
+ "foo-file" = 4
+ }
+}
+```
+
+
+```{tip}
+
+About `charm > revision` and `resources`:
+- If you specify only `charm > revision`: This is equivalent to `juju deploy --revision` or `juju refresh --revision` -- that is, the resource revision is automatically the latest.
+- If you specify only `resources`: This is equivalent to `juju attach-resource` -- that is, the resource revision is whatever you've specified.
+
+**Note:** While `juju refresh --resource` allows you to update a resource even if no update is available for the charm, this is not possible with `terraform juju`.
+
+```
+
+> See more: [`juju_application > resources`](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/application#resources)
+
+
+
+
+
+
+
+> **Contributors:** @cderici, @hmlanigan, @tmihoc
diff --git a/docs-rtd/howto/manage-charms.md b/docs-rtd/howto/manage-charms.md
new file mode 100644
index 00000000..b737c73b
--- /dev/null
+++ b/docs-rtd/howto/manage-charms.md
@@ -0,0 +1,57 @@
+(manage-charms)=
+# How to manage charms
+
+(deploy-a-charm)=
+## Deploy a charm
+
+```{important}
+
+The Terraform Provider for Juju does not support deploying a local charm.
+
+```
+
+To deploy a Charmhub charm, in your Terraform plan add a `juju_application` resource, specifying the target model and the charm:
+
+```terraform
+resource "juju_application" "this" {
+ model = juju_model.development.name
+
+ charm {
+ name = "hello-kubecon"
+ }
+}
+```
+
+> See more: [`juju_application` (resource)](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/application#schema)
+
+
+(update-a-charm)=
+## Update a charm
+
+
+To update a charm, in the application's resource definition, in the charm attribute, use a sub-attribute specifying a different revision or channel. For example:
+
+```terraform
+resource "juju_application" "this" {
+ model = juju_model.development.name
+
+ charm {
+ name = "hello-kubecon"
+ revision = 19
+ }
+
+}
+```
+
+> See more: [`juju_application` > `charm` > nested schema ](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/application#nested-schema-for-charm)
+
+## Remove a charm
+
+As a charm is just the *means* by which (an) application(s) are deployed, there is no way to remove the *charm* / *bundle*. What you *can* do, however, is remove the *application* / *model*.
+
+> See more: {ref}`remove-an-application`, {ref}`destroy-a-model`
+
+
+
+
+> **Contributors:** @aflynn, @hmlanigan, @tmihoc
diff --git a/docs-rtd/howto/manage-credentials.md b/docs-rtd/howto/manage-credentials.md
new file mode 100644
index 00000000..79536c40
--- /dev/null
+++ b/docs-rtd/howto/manage-credentials.md
@@ -0,0 +1,67 @@
+(manage-credentials)=
+# How to manage credentials
+
+> See also: [Credential](https://juju.is/docs/juju/credential)
+
+
+## Define a credential
+
+To define a credential, in your Terraform plan create a resource of the `juju_credential` type, specifying the credential's name, cloud, authentication type, and the attributes associated with the authentication type.
+
+
+```terraform
+resource "juju_credential" "this" {
+ name = "creddev"
+
+ cloud {
+ name = "localhost"
+ }
+
+ auth_type = "certificate"
+
+ attributes = {
+ client-cert = "/srv/cert.crt"
+ client-key = "/srv/cert.key"
+ trust-password = "S0m3P@$$w0rd"
+ }
+}
+```
+
+> See more: [`juju_credential` (resource)](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/credential)
+
+## Add a credential to a model
+> Who: User with controller `superuser` or model `admin` access.
+
+
+To add a controller credential to a model, in your Terraform plan, specify it as an attribute to the model definition. For example:
+
+```terraform
+resource "juju_model" "this" {
+ name = "development"
+
+ cloud {
+ name = "aws"
+ region = "eu-west-1"
+ }
+
+ credential = "juju_credential..name"
+}
+```
+
+
+## Update a credential
+
+To update a credential, in your Terraform plan, update its resource definition.
+
+> See more: [Resource `juju_credential`](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/credential)
+
+## Remove a credential
+
+To remove a credential, remove its resource definition from your Terraform plan.
+
+> See more: [Resource `juju_credential`](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/credential)
+
+
+
+
+> **Contributors:** @cderici, @erik-lonroth , @pedroleaoc, @pmatulis, @timclicks, @tmihoc, @wallyworld
diff --git a/docs-rtd/howto/manage-machines.md b/docs-rtd/howto/manage-machines.md
new file mode 100644
index 00000000..de255e28
--- /dev/null
+++ b/docs-rtd/howto/manage-machines.md
@@ -0,0 +1,55 @@
+(manage-machines)=
+# How to manage machines
+
+
+
+> See also: [`juju` | Machine](https://juju.is/docs/juju/machine)
+
+
+## Add a machine
+
+To add a machine to a model, in your Terraform plan add a resource of the `juju_machine` type, specifying the model.
+
+```terraform
+resource "juju_machine" "machine_0" {
+ model = juju_model.development.name
+}
+```
+
+You can optionally specify a base, a name, regular constraints, storage constraints, etc. You can also specify a `private_key_file`, `public_key_file`, and `ssh_address` -- that will allow you to add to the model an existing, manual machine (rather than a virtual one provisioned for you by the cloud).
+
+
+> See more: [`juju_machine` (resource)](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/machine)
+
+## Manage constraints for a machine
+> See also: [`juju` | Constraint](https://juju.is/docs/juju/constraint)
+
+To set constraints for a machine, in your Terraform plan, in the machine resource definition, set the constraints attribute to the desired quotes-enclosed, space separated list of key=value pairs. For example:
+
+```terraform
+resource "juju_machine" "machine_0" {
+ model = juju_model.development.name
+ name = "machine_0"
+ constraints = "tags=my-machine-tag"
+}
+```
+
+> See more: [`juju_machine` (resource)](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/machine)
+
+
+
+## Remove a machine
+> See also: [`juju` | Removing things](https://juju.is/docs/juju/removing-things)
+
+To remove a machine, remove its resource definition from your Terraform plan.
+
+> See more: [`juju_machine` (resource)](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/machine)
+
+
+
+
+> **Contributors:** @alhama7a, @cderici, @tmihoc
diff --git a/docs-rtd/howto/manage-models.md b/docs-rtd/howto/manage-models.md
new file mode 100644
index 00000000..4c58a698
--- /dev/null
+++ b/docs-rtd/howto/manage-models.md
@@ -0,0 +1,94 @@
+(manage-models)=
+# How to manage models
+
+> See also: [`juju` | Model](https://juju.is/docs/juju/model)
+
+## Add a model
+
+To add a model to the controller specified in the `juju` provider definition, in your Terraform plan create a resource of the `juju_model` type, specifying, at the very least, a name. For example:
+
+```terraform
+resource "juju_model" "testmodel" {
+ name = "machinetest"
+}
+
+```
+
+In the case of a multi-cloud controller, you can specify which cloud you want the model to be associated with by defining a `cloud` block. To specify a model configuration, include a `config` block.
+
+
+> See more: [`juju_model` (resource)](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/model)
+
+## Configure a model
+
+> See also: [`juju` | Model configuration](https://juju.is/docs/juju/configuration#heading--model-configuration), [`juju` | List of model configuration keys](https://juju.is/docs/juju/list-of-model-configuration-keys)
+>
+> See related: [`juju` | How to configure a controller](https://juju.is/docs/juju/manage-controllers#heading--configure-a-controller)
+
+With `terraform-provider-juju` you can only set configuration values, only for a specific model, and only a workload model; for anything else, please use the `juju` CLI.
+
+To configure a specific workload model, in your Terraform plan, in the model's resource definition, specify a `config` block, listing all the key=value pairs you want to set. For example:
+
+```terraform
+resource "juju_model" "this" {
+ name = "development"
+
+ cloud {
+ name = "aws"
+ region = "eu-west-1"
+ }
+
+ config = {
+ logging-config = "=INFO"
+ development = true
+ no-proxy = "jujucharms.com"
+ update-status-hook-interval = "5m"
+ }
+}
+```
+
+> See more: [`juju_model` (resource)](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/model)
+
+
+## Manage constraints for a model
+> See also: [`juju` | Constraint](https://juju.is/docs/juju/constraint)
+
+With `terraform-provider-juju` you can only set constraints -- to view them, please use the `juju` CLI.
+
+To set constraints for a model, in your Terraform, in the model's resource definition, specify the `constraints` attribute (value is a quotes-enclosed space-separated list of key=value pairs). For example:
+
+```terraform
+resource "juju_model" "this" {
+ name = "development"
+
+ cloud {
+ name = "aws"
+ region = "eu-west-1"
+ }
+
+ constraints = "cores=4 mem=16G"
+}
+```
+
+> See more: [`juju_model` (resource)](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/model)
+
+
+## Upgrade a model
+> See also: [`juju` | Upgrading things](https://juju.is/docs/juju/upgrading)
+
+To migrate a model to another controller, use the `juju` CLI to perform the migration, then, in your Terraform plan, reconfigure the `juju` provider to point to the destination controller (we recommend the method where you configure the provider using static credentials). You can verify your configuration changes by running `terraform plan` and noticing no change: Terraform merely compares the plan to what it finds in your deployment -- if model migration with `juju` has been successful, it should detect no change.
+
+
+> See more: {ref}`use-terraform-provider-juju`
+
+(destroy-a-model)=
+## Destroy a model
+
+To destroy a model, remove its resource definition from your Terraform plan.
+
+> See more: [`juju_model` (resource)](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/model)
+
+
+
+
+**Contributors:** @aflynn, @awnns, @barrettj12, @cderici, @hmlanigan, @pedroleaoc, @pmatulis, @serdarvural80, @timclicks, @tmihoc
diff --git a/docs-rtd/howto/manage-offers.md b/docs-rtd/howto/manage-offers.md
new file mode 100644
index 00000000..d1ecbb3b
--- /dev/null
+++ b/docs-rtd/howto/manage-offers.md
@@ -0,0 +1,91 @@
+(manage-offers)=
+# How to manage offers
+
+> See also: [`juju` | Offer](https://juju.is/docs/juju/offer)
+
+
+## Create an offer
+
+> Who: User with [offer `admin` access](https://juju.is/docs/juju/user-permissions#heading--offer-admin).
+
+To create an offer, in your Terraform plan, create a resource of the `juju_offer` type, specifying the offering model and the name of the application and application endpoint from which the offer is created:
+
+```terraform
+resource "juju_offer" "percona-cluster" {
+ model = juju_model.development.name
+ application_name = juju_application.percona-cluster.name
+ endpoint = "server"
+}
+```
+
+> See more: [`juju_offer` (resource)](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/offer)
+
+
+(integrate-with-an-offer)=
+## Integrate with an offer
+
+> Who: User with [offer `consume` access](https://juju.is/docs/juju/user-permissions#heading--offer-consume).
+
+To integrate with an offer, in your Terraform plan create a `juju_integration` resource as usual by specifying two application blocks and a `lifecycle > replace_triggered_by` block, but for the application representing the offer specify the `offer_url`, and in the `lifecycle` block list triggers only for the regular application (not the offer). For example:
+
+```terraform
+resource "juju_integration" "wordpress-db" {
+ model = juju_model.development-destination.name
+
+ application {
+ name = juju_application.wordpress.name
+ endpoint = "db"
+ }
+
+ application {
+ offer_url = juju_offer.this.url
+ }
+
+ lifecycle {
+ replace_triggered_by = [
+ juju_application.wordpress.name,
+ juju_application.wordpress.model,
+ juju_application.wordpress.constraints,
+ juju_application.wordpress.placement,
+ juju_application.wordpress.charm.name,
+ ]
+ }
+
+}
+
+```
+
+> See more: [`juju_integration` (resource)](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/integration)
+
+## Allow traffic from an integrated offer
+> Who: User with [offer `admin` access](https://juju.is/docs/juju/user-permissions#heading--offer-admin).
+
+To allow traffic from an integrated offer, in your Terraform plan, in the resource definition where you define the integration with an offer, use the `via` attribute to specify the list of CIDRs for outbound traffic. For example:
+
+
+
+```terraform
+resource "juju_integration" "this" {
+...
+ via = "10.0.0.0/24,10.0.1.0/24"
+
+# the rest of your integration definition
+
+}
+
+```
+
+> See more: [`juju_integration` > `via`](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/integration#via)
+
+
+## Remove an offer
+> Who: User with [offer `admin` access](https://juju.is/docs/juju/user-permissions#heading--offer-admin).
+
+To remove an offer, in your Terraform plan, remove its resource definition.
+
+> See more: [`juju_offer`](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/offer)
+
+
+
+
+> **Contributors:** @anvial, @cderici, @hmlanigan, @manadart, @simonrichardson, @tmihoc
diff --git a/docs-rtd/howto/manage-relations.md b/docs-rtd/howto/manage-relations.md
new file mode 100644
index 00000000..dbeab1ea
--- /dev/null
+++ b/docs-rtd/howto/manage-relations.md
@@ -0,0 +1,88 @@
+(manage-relations)=
+# How to manage relations
+
+> See also: [`juju` | Relation](https://juju.is/docs/juju/relation)
+
+## Add a relation
+
+
+
+### Add a same-model relation
+
+To add a same-model relation, create a resource of the `juju_integration` type, give it a label (below, `this`), and in its body add:
+- a `model` attribute specifying the name of the model where you want to create the relation;
+- two `application` blocks, specifying the names of the applications that you want to integrate (and, if necessary, their endpoints_;
+- a `lifecycle` block with the `replace_triggered_by` argument specifying the list of application attributes (always the name, model, constraints, placement, and charm name) for which, if they are changed = destroyed and recreated, the relation must be recreated as well.
+
+```{caution}
+
+**To avoid complications (e.g., race conditions) related to how Terraform works:**
+
+Make sure to always specify resources and data sources by reference rather than directly by name.
+
+For example, for a resource / data source of type `juju_model` with label `development` and name `mymodel`, do not specify it as `mymodel` but rather as `juju_model.development.name` / `data.juju_model.development.name`.
+
+
+```
+
+
+```terraform
+resource "juju_integration" "this" {
+ model = juju_model.development.name
+ via = "10.0.0.0/24,10.0.1.0/24"
+
+ application {
+ name = juju_application.wordpress.name
+ endpoint = "db"
+ }
+
+ application {
+ name = juju_application.percona-cluster.name
+ endpoint = "server"
+ }
+
+ # Add any RequiresReplace schema attributes of
+ # an application in this integration to ensure
+ # it is recreated if one of the applications
+ # is Destroyed and Recreated by terraform. E.G.:
+ lifecycle {
+ replace_triggered_by = [
+ juju_application.wordpress.name,
+ juju_application.wordpress.model,
+ juju_application.wordpress.constraints,
+ juju_application.wordpress.placement,
+ juju_application.wordpress.charm.name,
+ juju_application.percona-cluster.name,
+ juju_application.percona-cluster.model,
+ juju_application.percona-cluster.constraints,
+ juju_application.percona-cluster.placement,
+ juju_application.percona-cluster.charm.name,
+ ]
+ }
+}
+```
+
+> See more: [`juju_integration` (resource)](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/integration), [Terraform | `lifecycle` > `replace_triggered_by`](https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle#replace_triggered_by)
+
+
+
+### Add a cross-model relation
+
+In a cross-model relation there is also an 'offering' model and a 'consuming' model. The admin of the 'offering' model 'offers' an application for consumption outside of the model and grants an external user access to it. The user on the 'consuming' model can then find an offer to use, consume the offer, and integrate an application on their model with the 'offer' via the same `integrate` command as in the same-model case (just that the offer must be specified in terms of its offer URL or its consume alias). This creates a local proxy for the offer in the consuming model, and the application is subsequently treated as any other application in the model.
+
+> See more: {ref}`integrate-with-an-offer`
+
+
+
+## Remove a relation
+
+To remove a relation, in your Terraform plan, remove its resource definition.
+
+> See more: [`juju_integration` (resource)](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/integration)
+
+
+
+
+
+
+> **Contributors:** @amandahla, @aurelien-lourot , @cderici, @danieleprocida, @evilnick , @hmlanigan, @nottrobin , @pedroleaoc, @pmatulis, @tmihoc
diff --git a/docs-rtd/howto/manage-secrets.md b/docs-rtd/howto/manage-secrets.md
new file mode 100644
index 00000000..b32c0f39
--- /dev/null
+++ b/docs-rtd/howto/manage-secrets.md
@@ -0,0 +1,69 @@
+(manage-secrets)=
+# How to manage secrets
+
+> See also: [`juju` | Secret](https://juju.is/docs/juju/secret)
+
+Charms can use relations to share secrets, such as API keys, a database’s address, credentials and so on. This document demonstrates how to interact with them as a Juju user.
+
+```{caution}
+
+The write operations are only available (a) starting with Juju 3.3 and (b) to model admin users looking to manage user-owned secrets.
+```
+
+## Add a secret
+
+
+To add a (user) secret on the controller specified in the juju provider definition, in your Terraform plan create a resource of the `juju_secret` type, specifying, at the very least, a model, the name of the secret, a values map and, optionally, an info field. For example:
+
+```terraform
+resource "juju_secret" "my-secret" {
+ model = juju_model.development.name
+ name = "my_secret_name"
+ value = {
+ key1 = "value1"
+ key2 = "value2"
+ }
+ info = ""
+}
+```
+
+> See more: [`juju_secret` (resource)](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/secret)
+
+## Grant access to a secret
+
+
+Given a model that contains both your (user) secret and the application(s) that you want to grant access to, to grant the application(s) access to the secret, in your Terraform plan create a resource of the `juju_access_secret` type, specifying the model, the secret ID, and the application(s) that you wish to grant access to. For example:
+
+```
+resource "juju_access_secret" "my-secret-access" {
+ model = juju_model.development.name
+
+ # Use the secret_id from your secret resource or data source.
+ secret_id = juju_secret.my-secret.secret_id
+
+ applications = [
+ juju_application.app.name, juju_application.app2.name
+ ]
+}
+
+```
+
+> See more: [`juju_access_secret` (resource)](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/access_secret)
+
+
+## Update a secret
+
+> *This feature is opt-in because Juju automatically removing secret content might result in data loss.*
+
+
+To update a (user) secret, update its resource definition from your Terraform plan.
+
+## Remove a secret
+
+To remove a secret, remove its resource definition from your Terraform plan.
+
+> See more: [`juju_secret` (resource)](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/secret)
+
+
+
+> Contributors: @anvial, @cderici, @kelvin.liu , @tmihoc, @tony-meyer , @wallyworld
diff --git a/docs-rtd/howto/manage-ssh-keys.md b/docs-rtd/howto/manage-ssh-keys.md
new file mode 100644
index 00000000..0ff609cb
--- /dev/null
+++ b/docs-rtd/howto/manage-ssh-keys.md
@@ -0,0 +1,27 @@
+(manage-ssh-keys)=
+# How to manage SSH keys
+
+> See also: [`juju` | SSH key](https://juju.is/docs/juju/ssh-key)
+
+## Add an SSH key
+
+To add a public `ssh` key to a model, in your Terraform plan create a resource of the `juju_ssh_key` type, specifying the name of the model and the payload (here, the SSH key itself). For example:
+
+```text
+resource "juju_ssh_key" "mykey" {
+ model = juju_model.development.name
+ payload = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC1I8QDP79MaHEIAlfh933zqcE8LyUt9doytF3YySBUDWippk8MAaKAJJtNb+Qsi+Kx/RsSY02VxMy9xRTp9d/Vr+U5BctKqhqf3ZkJdTIcy+z4hYpFS8A4bECJFHOnKIekIHD9glHkqzS5Vm6E4g/KMNkKylHKlDXOafhNZAiJ1ynxaZIuedrceFJNC47HnocQEtusPKpR09HGXXYhKMEubgF5tsTO4ks6pplMPvbdjxYcVOg4Wv0N/LJ4ffAucG9edMcKOTnKqZycqqZPE6KsTpSZMJi2Kl3mBrJE7JbR1YMlNwG6NlUIdIqVoTLZgLsTEkHqWi6OExykbVTqFuoWJJY3BmRAcP9H3FdLYbqcajfWshwvPM2AmYb8V3zBvzEKL1rpvG26fd3kGhk3Vu07qAUhHLMi3P0McEky4cLiEWgI7UyHFLI2yMRZgz23UUtxhRSkvCJagRlVG/s4yoylzBQJir8G3qmb36WjBXxpqAGHfLxw05EQI1JGV3ReYOs= user@somewhere"
+}
+```
+
+> See more: [`juju_ssh_key` (resource)](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/ssh_key)
+
+## Remove an SSH key
+
+To remove an SSH key, remove its resource definition from your Terraform plan.
+
+> See more: [`juju_ssh_key` (resource)](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/ssh_key)
+
+
+
+> **Contributors:** @cderici, @hmlanigan, @tmihoc
diff --git a/docs-rtd/howto/manage-units.md b/docs-rtd/howto/manage-units.md
new file mode 100644
index 00000000..8448ff3f
--- /dev/null
+++ b/docs-rtd/howto/manage-units.md
@@ -0,0 +1,30 @@
+(manage-units)=
+# How to manage units
+
+> See also: [`juju` | Unit](https://juju.is/docs/juju/unit)
+
+(control-the-number-of-units)=
+## Control the number of units
+
+To control the number of units of an application, in its resource definition specify a `units` attribute. For example, below we set it to 3.
+
+
+```terraform
+resource "juju_application" "this" {
+ model = juju_model.development.name
+
+ charm {
+ name = "hello-kubecon"
+ }
+
+ units = 3
+}
+```
+
+> See more: [`juju_application` (resource)](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/application#schema)
+
+
+
+
+
+> **Contributors:** @cderici, @hmlanigan, @skourta, @tmihoc
diff --git a/docs-rtd/howto/manage-users.md b/docs-rtd/howto/manage-users.md
new file mode 100644
index 00000000..3eb3ac8f
--- /dev/null
+++ b/docs-rtd/howto/manage-users.md
@@ -0,0 +1,61 @@
+(manage-users)=
+# How to manage users
+
+> See also: [`juju` | User](https://juju.is/docs/juju/user)
+
+## Add a user
+
+To add a user to a controller, in your Terraform plan add a `juju_user` resource, specifying a label, a name, and a password. For example:
+
+```terraform
+resource "juju_user" "alex" {
+ name = "alex"
+ password = "alexsupersecretpassword"
+
+}
+```
+
+> See more: [`juju_user` (resource)](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/user)
+
+
+## Manage a user's access level
+> See also: [`juju` | User access levels](https://juju.is/docs/juju/user-permissions)
+
+With `terraform-provider-juju` you can manage user access only at the model level; for anything else, please use the `juju` CLI.
+
+To grant a user access to a model, in your Terraform plan add a `juju_access_model` resource, specifying the model, the access level, and the user(s) to which you want to grant access. For example:
+
+```terraform
+resource "juju_access_model" "this" {
+ model = juju_model.dev.name
+ access = "write"
+ users = [juju_user.dev.name, juju_user.qa.name]
+}
+```
+
+> See more: [`juju_access_model`](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/access_model)
+
+## Manager a user's login details
+
+To set or change a user's password, in your Terraform plan add, in the relevant `juju_user` resource definition, change the `password` attribute to the desired value. For example:
+
+```terraform
+resource "juju_user" "alex" {
+ name = "alex"
+ password = "alexnewsupersecretpassword"
+
+}
+```
+
+> See more: [`juju_user`](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/user#password)
+
+## Remove a user
+
+To remove a user, in your Terraform plan remove its resource definition.
+
+> See more: [`juju_user` (resource)](https://registry.terraform.io/providers/juju/juju/latest/docs/resources/user)
+
+
+
+
+> **Contributors:** @cderici, @hmlanigan, @pedroleaoc, @pmatulis, @timclicks, @tmihoc
diff --git a/docs-rtd/index.md b/docs-rtd/index.md
new file mode 100644
index 00000000..0d0d9862
--- /dev/null
+++ b/docs-rtd/index.md
@@ -0,0 +1,87 @@
+# Terraform Provider for Juju (`terraform-provider-juju`)
+
+```{toctree}
+:maxdepth: 2
+:hidden: true
+
+tutorial
+howto/index
+```
+
+
+
+The Terraform Provider for Juju (henceforth, `terraform-provider-juju`) is a [Terraform Provider](https://developer.hashicorp.com/terraform/language/providers) that extends [Terraform](https://developer.hashicorp.com/terraform) with [Juju](https://juju.is) functionality.
+
+When you're putting together your Terraform plan, if you specify `juju` as the provider, you can connect to a pre-existing Juju controller (created with the [`juju` CLI](https://juju.is/docs/juju/juju-client)) and then go ahead and use it to do Juju things -- easy deploy, configure, integrate, scale, etc., applications on any Juju-supported cloud (Kubernetes or otherwise) using [charms](https://juju.is/docs/juju/charmed-operator).
+
+`terraform-provider-juju` combines the power of Terraform -- comprehensive infrastructure management, declaratively -- with the power of Juju -- easy systems management, from Day 0 to Day n.
+
+Like all of Juju, `terraform-provider-juju` is for SREs, or anyone looking to take control of cloud.
+
+---------
+
+## In this documentation
+
+````{grid} 1 1 2 2
+
+```{grid-item-card} [Tutorial](tutorial)
+:link: tutorial
+:link-type: doc
+
+**Start here**: a hands-on introduction to Example Product for new users
+```
+
+```{grid-item-card} [How-to guides](/index)
+:link: howto/index
+:link-type: doc
+
+**Step-by-step guides** covering key operations and common tasks
+```
+
+````
+
+
+
+---------
+
+
+## Project and community
+
+Example Project is a member of the Ubuntu family. It’s an open source project that warmly welcomes community projects, contributions, suggestions, fixes and constructive feedback.
+
+* **[Read our code of conduct](https://ubuntu.com/community/ethos/code-of-conduct)**:
+As a community we adhere to the Ubuntu code of conduct.
+
+* **[Get support](https://discourse.charmhub.io/)**:
+Discourse is the go-to forum for all questions Juju.
+
+* **[Join our online chat](https://matrix.to/#/#terraform-provider-juju:ubuntu.com)**:
+Meet us in the `#terraform-provider-juju` channel on Matrix.
+
+* **[Report bugs](https://github.com/juju/terraform-provider-juju/issues/new?title=doc%3A+ADD+A+TITLE&body=DESCRIBE+THE+ISSUE%0A%0A---%0ADocument:%20index.md)**:
+We want to know about the problems so we can fix them.
+
+* **[Contribute docs](https://github.com/juju/terraform-provider-juju/tree/main/docs)**:
+The documentation sources on GitHub.
diff --git a/docs-rtd/reuse/links.txt b/docs-rtd/reuse/links.txt
new file mode 100644
index 00000000..f9d3d5cd
--- /dev/null
+++ b/docs-rtd/reuse/links.txt
@@ -0,0 +1 @@
+.. _link text: https://example.com
diff --git a/docs-rtd/tutorial.md b/docs-rtd/tutorial.md
new file mode 100644
index 00000000..9ea95928
--- /dev/null
+++ b/docs-rtd/tutorial.md
@@ -0,0 +1,395 @@
+# Tutorial
+
+
+
+Imagine your business needs a chat service such as Mattermost backed up by a database such as PostgreSQL. In a traditional setup, this can be quite a challenge, but with Juju you'll find yourself deploying, configuring, scaling, integrating, etc., applications in no time. Let's get started!
+
+----------
+**What you'll need:**
+- A workstation, e.g., a laptop, that has sufficient resources to launch a virtual machine with 4 CPUs, 8 GB RAM, and 50 GB disk space.
+
+**What you'll do:**
+- Set up an isolated test environment with Multipass and the `charm-dev` blueprint, which will provide all the necessary tools and configuration for the tutorial (a localhost machine cloud and Kubernetes cloud, Juju, etc.).
+
+- Plan, then deploy, configure, and scale a chat service based on Mattermost and backed by PostgreSQL on a local Kubernetes cloud with Juju.
+----------
+
+
+## Set up an isolated test environment
+
+```{important}
+
+**Tempted to skip this step?** We strongly recommend that you do not! As you will see in a minute, the VM you set up in this step does not just provide you with an isolated test environment but also with almost everything else you’ll need in the rest of this tutorial (and the non-VM alternative may not yield exactly the same results).
+```
+
+Follow the instructions for the `juju` CLI.
+
+> See more: [`juju` | Tutorial > Set things up](https://juju.is/docs/juju/tutorial#set-up-an-isolated-test-environment)
+
+In addition to that, on your local workstation, create a directory called `terraform-juju`, then use Multipass to mount it to your Multipass VM. For example, on Linux:
+
+```text
+user@ubuntu:~$ mkdir terraform-juju
+user@ubuntu:~$ cd terraform-juju/
+user@ubuntu:~$ multipass mount ~/terraform-juju my-juju-vm:~/terraform-juju
+```
+
+This setup will enable you to create and edit Terraform files in your local editor while running them inside your VM.
+
+
+## Plan
+
+In this tutorial your goal is to set up a chat service on a cloud.
+
+First, decide which cloud (i.e., anything that provides storage, compute, and networking) you want to use. Juju supports a long list of clouds; in this tutorial we will use a low-ops, minimal production Kubernetes called 'MicroK8s'. In a terminal, open a shell into your VM and verify that you already have MicroK8s installed (`microk8s version`).
+
+> See more: [`juju` | Cloud](https://juju.is/docs/juju/cloud), [`juju` | List of supported clouds](https://juju.is/docs/juju/juju-supported-clouds), [The MicroK8s cloud and Juju](https://juju.is/docs/juju/microk8s), [How to set up your test environment automatically > steps 3-4](https://juju.is/docs/juju/set-up--tear-down-your-test-environment#set-up-tear-down-automatically)
+
+Next, decide which charms (i.e., software operators) you want to use. Charmhub provides a large collection. For this tutorial we will use `mattermost-k8s` for the chat service, `postgresql-k8s` for its backing database, and `self-signed-certificates` to TLS-encrypt traffic from PostgreSQL.
+
+> See more: [`juju` | Charm](https://juju.is/docs/juju/charmed-operator), [Charmhub](https://charmhub.io/), Charmhub | [`mattermost-k8s`](https://charmhub.io/mattermost-k8s), [`postgresql-k8s`](https://charmhub.io/postgresql-k8s), [`self-signed-certificates`](https://charmhub.io/self-signed-certificates)
+
+
+## Deploy, configure, integrate
+
+You will need to install a Juju client; on the client, add your cloud and cloud credentials; on the cloud, bootstrap a controller (i.e., control plan); on the controller, add a model (i.e., canvas to deploy things on; namespace); on the model, deploy, configure, and integrate the charms that make up your chat service.
+
+`terraform-provider-juju` is not self-sufficient -- follow the instructions for the `juju` CLI all the way up to and including the step where you create the `34microk8s` controller. Also get the details of that controller: `juju show-controller --show-password 34microk8s`.
+
+> See more: [`juju` | Tutorial > Deploy](https://juju.is/docs/juju/tutorial#deploy)
+
+Then, on your VM, install the `terraform` CLI:
+
+```text
+ubuntu@my-juju-vm:~$ sudo snap install terraform --classic
+terraform 1.7.5 from Snapcrafters✪ installed
+```
+
+Next, in your local `terraform-juju` directory, create three files as follows:
+
+(a) a `terraform.tf`file , where you'll configure `terraform` to use the `juju` provider:
+
+```text
+terraform {
+ required_providers {
+ juju = {
+ version = "~> 0.11.0"
+ source = "juju/juju"
+ }
+ }
+}
+```
+
+(b) a `ca-cert.pem` file, where you'll copy-paste the `ca_certificate` from the details of your `juju`-client-bootstrapped controller; and
+
+(c) a `main.tf` file, where you'll configure the `juju` provider to point to the `juju`-client-bootstrapped controller and the `ca-cert.pem` file where you've saved it's certificate, then create resources to add a model and deploy, configure, and integrate applications:
+
+```terraform
+provider "juju" {
+ controller_addresses = "10.152.183.27:17070"
+ username = "admin"
+ password = "40ec19f8bebe353e122f7f020cdb6949"
+ ca_certificate = file("~/terraform-juju/ca-cert.pem")
+}
+
+resource "juju_model" "chat" {
+ name = "chat"
+}
+
+resource "juju_application" "mattermost-k8s" {
+ model = juju_model.chat.name
+
+ charm {
+ name = "mattermost-k8s"
+ }
+
+}
+
+resource "juju_application" "postgresql-k8s" {
+
+ model = juju_model.chat.name
+
+ charm {
+ name = "postgresql-k8s"
+ channel = "14/stable"
+ }
+
+ trust = true
+
+ config = {
+ profile = "testing"
+ }
+
+}
+
+resource "juju_application" "self-signed-certificates" {
+ model = juju_model.chat.name
+
+ charm {
+ name = "self-signed-certificates"
+ }
+
+}
+
+resource "juju_integration" "postgresql-mattermost" {
+ model = juju_model.chat.name
+
+ application {
+ name = juju_application.postgresql-k8s.name
+ endpoint = "db"
+ }
+
+ application {
+ name = juju_application.mattermost-k8s.name
+ }
+
+ # Add any RequiresReplace schema attributes of
+ # an application in this integration to ensure
+ # it is recreated if one of the applications
+ # is Destroyed and Recreated by terraform. E.G.:
+ lifecycle {
+ replace_triggered_by = [
+ juju_application.postgresql-k8s.name,
+ juju_application.postgresql-k8s.model,
+ juju_application.postgresql-k8s.constraints,
+ juju_application.postgresql-k8s.placement,
+ juju_application.postgresql-k8s.charm.name,
+ juju_application.mattermost-k8s.name,
+ juju_application.mattermost-k8s.model,
+ juju_application.mattermost-k8s.constraints,
+ juju_application.mattermost-k8s.placement,
+ juju_application.mattermost-k8s.charm.name,
+ ]
+ }
+}
+
+resource "juju_integration" "postgresql-tls" {
+ model = juju_model.chat.name
+
+ application {
+ name = juju_application.postgresql-k8s.name
+ }
+
+ application {
+ name = juju_application.self-signed-certificates.name
+ }
+
+ # Add any RequiresReplace schema attributes of
+ # an application in this integration to ensure
+ # it is recreated if one of the applications
+ # is Destroyed and Recreated by terraform. E.G.:
+ lifecycle {
+ replace_triggered_by = [
+ juju_application.postgresql-k8s.name,
+ juju_application.postgresql-k8s.model,
+ juju_application.postgresql-k8s.constraints,
+ juju_application.postgresql-k8s.placement,
+ juju_application.postgresql-k8s.charm.name,
+ juju_application.self-signed-certificates.name,
+ juju_application.self-signed-certificates.model,
+ juju_application.self-signed-certificates.constraints,
+ juju_application.self-signed-certificates.placement,
+ juju_application.self-signed-certificates.charm.name,
+ ]
+ }
+}
+```
+
+Next, in your Multipass VM, initialise your provider's configuration (`terraform init`), preview your plan (`terraform plan`), and apply your plan to your infrastructure (`terraform apply`):
+
+```{important}
+You can always repeat all three, though technically you only need to run `terraform init` if your `terraform.tf` or the `provider` bit of your `main.tf` has changed, and you only need to run `terraform plan` if you want to preview the changes before applying them.
+```
+
+```text
+ubuntu@my-juju-vm:~/terraform-juju$ terraform init && terraform plan && terraform apply
+```
+
+Finally, use the `juju` client to inspect the results:
+
+```text
+ubuntu@my-juju-vm:~/terraform-juju$ juju status --relations
+```
+
+Done!
+
+Now, from the output of `juju status`> `Unit` > `mattermost-k8s/0`, retrieve the IP address and the port and feed them to `curl` on the template below:
+
+```text
+curl :/api/v4/system/ping
+```
+
+Sample session:
+
+```text
+ubuntu@my-juju-vm:~$ curl 10.1.170.150:8065/api/v4/system/ping
+{"ActiveSearchBackend":"database","AndroidLatestVersion":"","AndroidMinVersion":"","IosLatestVersion":"","IosMinVersion":"","status":"OK"}
+```
+
+Congratulations, your chat service is up and running!
+
+> See more: [`juju` | How to set up your test environment automatically > steps 3-4](https://juju.is/docs/juju/set-up--tear-down-your-test-environment), {ref}`install-and-manage-terraform-provider-juju`, [`juju` | How to manage clouds](https://juju.is/docs/juju/manage-clouds), {ref}`manage-credentials`, [`juju` | How to manage controllers](https://juju.is/docs/juju/manage-controllers), {ref}`manage-models`, {ref}`manage-applications`
+
+
+## Scale
+
+A database failure can be very costly. Let's scale it!
+
+On your local machine, in you `main.tf` file, in the definition of the resource for `postgresql-k8s`, add a `units` block and set it to `3`:
+
+```terraform
+provider "juju" {
+ controller_addresses = "10.152.183.27:17070"
+ username = "admin"
+ password = "40ec19f8bebe353e122f7f020cdb6949"
+ ca_certificate = file("~/terraform-juju/ca-cert.pem")
+}
+
+resource "juju_model" "chat" {
+ name = "chat"
+}
+
+
+resource "juju_application" "mattermost-k8s" {
+ model = juju_model.chat.name
+
+ charm {
+ name = "mattermost-k8s"
+ }
+
+}
+
+
+resource "juju_application" "postgresql-k8s" {
+
+ model = juju_model.chat.name
+
+ charm {
+ name = "postgresql-k8s"
+ channel = "14/stable"
+ }
+
+ trust = true
+
+ config = {
+ profile = "testing"
+ }
+
+ units = 3
+
+}
+
+
+resource "juju_application" "self-signed-certificates" {
+ model = juju_model.chat.name
+
+ charm {
+ name = "self-signed-certificates"
+ }
+
+}
+
+
+resource "juju_integration" "postgresql-mattermost" {
+ model = juju_model.chat.name
+
+ application {
+ name = juju_application.postgresql-k8s.name
+ endpoint = "db"
+ }
+
+ application {
+ name = juju_application.mattermost-k8s.name
+ }
+
+ # Add any RequiresReplace schema attributes of
+ # an application in this integration to ensure
+ # it is recreated if one of the applications
+ # is Destroyed and Recreated by terraform. E.G.:
+ lifecycle {
+ replace_triggered_by = [
+ juju_application.postgresql-k8s.name,
+ juju_application.postgresql-k8s.model,
+ juju_application.postgresql-k8s.constraints,
+ juju_application.postgresql-k8s.placement,
+ juju_application.postgresql-k8s.charm.name,
+ juju_application.mattermost-k8s.name,
+ juju_application.mattermost-k8s.model,
+ juju_application.mattermost-k8s.constraints,
+ juju_application.mattermost-k8s.placement,
+ juju_application.mattermost-k8s.charm.name,
+ ]
+ }
+}
+
+
+resource "juju_integration" "postgresql-tls" {
+ model = juju_model.chat.name
+
+ application {
+ name = juju_application.postgresql-k8s.name
+ }
+
+ application {
+ name = juju_application.self-signed-certificates.name
+ }
+
+ # Add any RequiresReplace schema attributes of
+ # an application in this integration to ensure
+ # it is recreated if one of the applications
+ # is Destroyed and Recreated by terraform. E.G.:
+ lifecycle {
+ replace_triggered_by = [
+ juju_application.postgresql-k8s.name,
+ juju_application.postgresql-k8s.model,
+ juju_application.postgresql-k8s.constraints,
+ juju_application.postgresql-k8s.placement,
+ juju_application.postgresql-k8s.charm.name,
+ juju_application.self-signed-certificates.name,
+ juju_application.self-signed-certificates.model,
+ juju_application.self-signed-certificates.constraints,
+ juju_application.self-signed-certificates.placement,
+ juju_application.self-signed-certificates.charm.name,
+ ]
+ }
+}
+```
+
+Then, in your VM, use `terraform` to apply the changes and `juju` to inspect the results:
+
+```text
+ubuntu@my-juju-vm:~/terraform-juju$ terraform init && terraform plan && terraform apply
+ubuntu@my-juju-vm:~/terraform-juju$ juju status --relations
+```
+
+> See more: {ref}`scale-an-application`
+
+
+## Tear down your test environment
+
+Follow the instructions for the `juju` CLI.
+
+> See more: [`juju` | Tutorial > Tear things down](https://juju.is/docs/juju/tutorial#tear-down-your-test-environment)
+
+In addition to that, on your host machine, delete your `terraform-provider-juju` directory.
+
+
+
+
+> **Contributors:** @ancollins, @degville , @fernape, @hmlanigan, @houz42, @hpidcock, @kayrag2 , @keirthana , @manadart, @michaeldmitry, @mrbarco, @nsakkos, @ppasotti, @selcem, @shrishtikarkera, @thp, @tmihoc, @wideawakening , @sinclert
diff --git a/init.sh b/init.sh
new file mode 100755
index 00000000..3926b4c8
--- /dev/null
+++ b/init.sh
@@ -0,0 +1,171 @@
+#!/bin/bash
+
+set -euo pipefail
+
+# Check if the script is running in the expected root directory
+if [ ! -e ".git" ]; then
+ echo "ERROR: This script must be run from the root directory of the repository."
+ exit 1
+fi
+
+# Check if an installation directory argument is supplied; if not, prompt for it
+install_directory="${1:-}"
+if [ -z "$install_directory" ]; then
+
+ read -rp "Enter the installation directory (e.g., '.' or 'docs'): " install_directory
+fi
+
+# Check if md or rst is preferred for the documentation being built
+promptForFileChoice() {
+ while true; do
+ read -p "Will you be using the 'rst' or 'md' file format for the documentation (default: 'rst'): " filetype_choice
+
+ filetype_choice=${filetype_choice:-rst}
+
+ if [ "$filetype_choice" = "md" ] || [ "$filetype_choice" = "rst" ]; then
+ file_type="$filetype_choice"
+ echo "Setting filetype to: $file_type"
+ break
+ else
+ echo "Invalid input. Please enter either 'md' or 'rst':"
+ fi
+ done
+}
+
+# If default variable for filetype choice is defined in CI then don't prompt user for choice
+if [ -z "${default_filetype_choice:-}" ]; then
+ promptForFileChoice
+else
+ file_type="$default_filetype_choice"
+ echo "Using predefined filetype choice: $file_type"
+fi
+
+# Normalise the install_directory path
+install_directory=$(realpath -m --relative-to="$(pwd)" "$install_directory")
+echo "Installing at $install_directory..."
+
+# Come up with a unique temporary directory name based on the current timestamp
+temp_directory="temp-starter-pack-$(date +%Y%m%d%H%M%S)"
+
+# Clone the starter pack repository into the temporary directory and de-git it
+echo "Cloning the starter pack repository..."
+git clone --depth 1 -b main --single-branch https://github.com/canonical/starter-pack "$temp_directory"
+rm -rf "$temp_directory/.git"
+
+# Update workflow and documentation files based on the installation directory
+echo "Updating working directory in workflow files..."
+sed -i "s|working-directory:\s*'\.'|working-directory: '$install_directory'|g" "$temp_directory/sp-files/.github/workflows"/*
+echo "Updating .readthedocs.yaml configuration..."
+sed -i "s|configuration:\s*sp-docs/conf\.py|configuration: $install_directory/conf.py|g" "$temp_directory/sp-files/.readthedocs.yaml"
+sed -i "s|requirements:\s*sp-docs/\.sphinx/requirements\.txt|requirements: $install_directory/.sphinx/requirements.txt|g" "$temp_directory/sp-files/.readthedocs.yaml"
+echo "Updating contribution guide..."
+sed -i "s|DOCDIR|$install_directory|g" "$temp_directory/sp-files/contributing.rst"
+[ "$install_directory" != "." ] && sed -i "s/Makefile.sp/$install_directory\/Makefile.sp/" "$temp_directory/sp-files/.github/workflows/sphinx-python-dependency-build-checks.yml"
+[ "$install_directory" != "." ] && sed -i "s/.sphinx\/.markdownlint.json/$install_directory\/.sphinx\/.markdownlint.json/" "$temp_directory/sp-files/.github/workflows/markdown-style-checks.yml"
+
+# Update the GitHub folder path in the configuration file
+echo "Updating conf.py configuration..."
+github_folder="/$install_directory/"
+[ "$install_directory" == "." ] && github_folder="/"
+sed -i "s|'github_folder':\s*'/sp-docs/'|'github_folder': '$github_folder'|g" "$temp_directory/sp-files/conf.py"
+
+# Tell that the directory's about to be created if it doesn't exist
+if [ ! -d "$install_directory" ]; then
+ echo "Creating the installation directory: $install_directory"
+ mkdir -p "$install_directory"
+fi
+
+# Check if .gitignore exists in the destination directory
+# If it does, append the contents of the source .gitignore to the destination
+if [ -f "$install_directory/.gitignore" ]; then
+ echo "ACTION REQUIRED: .gitignore already exists in the destination directory."
+ read -p "Do you want to append the list of ignored files for Sphinx docs to the existing .gitignore? Enter 'n' to skip. (y/n): " confirm
+ if [ "$confirm" = "y" ]; then
+ echo "Appending contents to the existing .gitignore..."
+ cat "$temp_directory/sp-files/.gitignore" >>"$install_directory/.gitignore"
+ else
+ echo "Operation skipped by the user. Add the .gitignore rules for the Sphinx docs to your .gitignore file manually."
+ fi
+ rm "$temp_directory/sp-files/.gitignore"
+fi
+
+# Check if Makefile exists in the destination directory
+if [ -f "$install_directory/Makefile" ]; then
+ echo "ACTION REQUIRED: Makefile already exists in the destination directory. Check the contents before running the targets!"
+ read -p "Do you want to add the Sphinx docs targets into the Makefile? The existing file will be saved a backup file. Enter 'n' to skip. (y/n): " confirm
+ if [ "$confirm" = "y" ]; then
+ # Create a copy of the existing Makefile as backup
+ existing_makefile="$install_directory/Makefile"
+ backup_makefile="$install_directory/Makefile.backup.$(date +%Y%m%d%H%M%S)"
+ echo "Creating a backup: $backup_makefile"
+ cp "$existing_makefile" "$backup_makefile"
+
+ echo "Appending Sphinx docs targets to the existing Makefile..."
+ echo "" >>"$existing_makefile" # Add a new line before appending the contents
+ cat "$temp_directory/sp-files/Makefile" >>"$existing_makefile"
+ else
+ echo "Operation skipped by the user. Add the Makefile targets for Sphinx docs manually."
+ fi
+ rm "$temp_directory/sp-files/Makefile"
+fi
+
+# Copy the rest of the starter pack repository to the installation directory
+echo "Copying contents to the installation directory..."
+cp -R "$temp_directory"/sp-files/* "$temp_directory"/sp-files/.??* "$install_directory"
+
+# Delete files not of preferred filetype in the installation directory, rst preferred default
+# No wildcard delete to avoid data loss if user Git-inits in dir with pre-existing files
+if [ "$file_type" = 'md' ]; then
+ echo "Deleting .rst files..."
+ rm "$install_directory"/contributing.rst
+ rm "$install_directory"/doc-cheat-sheet.rst
+ rm "$install_directory"/index.rst
+ for file in "$install_directory"/*-myst.md; do
+ mv "$file" "${file/-myst.md/.md}"
+ done
+
+else
+ echo "Deleting .md files..."
+ rm "$install_directory"/contributing-myst.md
+ rm "$install_directory"/doc-cheat-sheet-myst.md
+ rm "$install_directory"/index-myst.md
+fi
+
+# Ensure GitHub workflows and woke config are placed in the repo root
+# if installing in a non-root directory
+if [ "$install_directory" != "." ]; then
+ echo "Handling GitHub workflow files and .wokeignore configuration..."
+ mkdir -p .github/workflows
+ for file in "$install_directory/.github/workflows/"*; do
+ [ -f "$file" ] || continue
+ basefile=$(basename "$file")
+ if [ ! -f .github/workflows/"$basefile" ]; then
+ mv "$file" .github/workflows/
+ else
+ echo "ACTION REQUIRED: GitHub workflow '$basefile' already exists and was not overwritten."
+ fi
+ done
+ rmdir -p --ignore-fail-on-non-empty "$install_directory/.github/workflows"
+
+ if [ -f "$install_directory/.wokeignore" ]; then
+ if [ -f .wokeignore ]; then
+ echo "ACTION REQUIRED: A .wokeignore file already exists in the root directory."
+ read -p "Do you want to append the contents of $install_directory/.wokeignore to the existing .wokeignore? Enter 'n' to skip. (y/n): " confirm
+ if [ "$confirm" = "y" ]; then
+ echo "Appending contents to the existing .wokeignore..."
+ cat "$install_directory/.wokeignore" >>.wokeignore
+ rm "$install_directory/.wokeignore"
+ else
+ echo "Operation skipped by the user. Add the rules from $install_directory/.wokeignore to your .wokeignore file manually."
+ fi
+ else
+ ln -s "$install_directory/.wokeignore" .wokeignore
+ fi
+ fi
+fi
+
+# Clean up the temporary directory
+echo "Cleaning up temporary files..."
+rm -rf "$temp_directory"
+
+echo "Setup successfully completed!"