Right now clickhouse allows to create TTL columns for Distributed tables during alters. It is working normally until server restart. After that it won't start because engine distributed doesn't support TTL clause. Modify metadata is required.

My cluster has 21.3 but tested it also with 21.11 and the same behavior.
It is blocked during create but it should be also be blocked during alters.
Tested on table from tutorial
ENGINE = Distributed('stage, 'default', 'hits_v1') 
alter table hits_v1_all modify column UTMCampaign String TTL EventDate + INTERVAL 1 MONTH ← it passes normally
virtual void checkAlterIsPossible(const AlterCommands & commands, ContextPtr context) const;
    /**
      * Checks that mutation commands can be applied to storage.
      */
    virtual void checkMutationIsPossible(const MutationCommands & commands, const Settings & settings) const;
    /** ALTER tables with regard to its partitions.
      * Should handle locks for each command on its own.
      */
    virtual Pipe alterPartition(
        const StorageMetadataPtr & ,
        const PartitionCommands & ,
        ContextPtr );
    
    virtual void checkAlterPartitionIsPossible(const PartitionCommands & commands, const StorageMetadataPtr & metadata_snapshot, const Settings & settings) const;
    /** Perform any background work. For example, combining parts in a MergeTree type table.
      * Returns whether any work has been done.
      */
    virtual bool optimize(
        const ASTPtr & ,
        const StorageMetadataPtr & ,
        const ASTPtr & ,
        bool ,
        bool ,
        const Names & ,
        ContextPtr )
    {
        throw Exception("Method optimize is not supported by storage " + getName(), ErrorCodes::NOT_IMPLEMENTED);
    }
    
    virtual void mutate(const MutationCommands &, ContextPtr)